ToolDeck

เข้ารหัส Base64 ใน Java 8+

·Java Security & API Engineer·ตรวจสอบโดยPavel Novak·เผยแพร่เมื่อ

ใช้ ตัวเข้ารหัส Base64 ออนไลน์ ฟรีโดยตรงในเบราว์เซอร์ของคุณ — ไม่ต้องติดตั้ง

ลอง ตัวเข้ารหัส Base64 ออนไลน์ ออนไลน์ →

ทุกครั้งที่ต้องสร้าง HTTP Basic Auth header ฝังใบรับรองใน Kubernetes secret หรือส่งข้อมูลไบนารีผ่าน JSON API ขั้นตอนแรกเหมือนกันทุกครั้ง: เข้ารหัส Base64 ไบต์ดิบให้เป็น สตริงที่ปลอดภัยสำหรับ ASCII Java ทำสิ่งนี้ได้อย่างตรงไปตรงมาด้วย java.util.Base64, API มาตรฐานที่มีมาตั้งแต่ Java 8 ซึ่งมาแทนที่ sun.misc.BASE64Encoder ที่ถูก deprecated ไปแล้ว สำหรับการเข้ารหัสแบบครั้งเดียวโดยไม่ต้องเขียนโค้ด Base64 Encoder ของ ToolDeck รองรับการใช้งานได้ทันทีในเบราว์เซอร์ คู่มือนี้ครอบคลุม Base64.getEncoder(), getUrlEncoder(), getMimeEncoder(), การเข้ารหัสไฟล์, การสตรีมด้วย wrap(OutputStream), และข้อผิดพลาดที่นักพัฒนา Java ที่มีประสบการณ์มักสะดุดด้วย ทุกตัวอย่างคอมไพล์ได้บน Java 8 ถึง Java 21+

  • Base64.getEncoder().encodeToString(bytes) คือวิธีมาตรฐานแบบบรรทัดเดียว — ติดมากับ JDK ตั้งแต่ Java 8 ไม่เปลี่ยนแปลงใน Java 17 และ 21
  • ต้องระบุ StandardCharsets.UTF_8 ให้กับ String.getBytes() ก่อนเข้ารหัสเสมอ — ถ้าไม่ระบุจะใช้ค่าเริ่มต้นของแพลตฟอร์ม ซึ่งต่างกันในแต่ละ JVM
  • getUrlEncoder() สร้างผลลัพธ์แบบ URL-safe (- แทน +, _ แทน /) และ withoutPadding() ตัดอักขระ = ท้ายสตริงออก
  • getMimeEncoder() แทรกการขึ้นบรรทัดใหม่ทุก 76 ตัวอักษร — จำเป็นสำหรับอีเมล (MIME) และรูปแบบ PEM certificate
  • สำหรับไฟล์ขนาดใหญ่ ใช้ Base64.getEncoder().wrap(OutputStream) เพื่อสตรีมโดยไม่โหลดทั้งไฟล์เข้าหน่วยความจำ

Base64 Encoding คืออะไร?

Base64 แปลงข้อมูลไบนารีใดก็ได้เป็นสตริงที่ประกอบด้วยอักขระ ASCII ที่พิมพ์ได้ 64 ตัว ได้แก่ A-Z, a-z, 0-9, + และ /ทุก 3 ไบต์ของข้อมูลนำเข้าจะสร้างอักขระ Base64 ได้พอดี 4 ตัว หากความยาวข้อมูลนำเข้าไม่เป็น จำนวนเท่าของ 3 จะเติมอักขระ = หนึ่งหรือสองตัวต่อท้าย ผลลัพธ์ที่เข้ารหัสจะมีขนาดใหญ่กว่าข้อมูลต้นฉบับประมาณ 33%

Base64 ไม่ใช่การเข้ารหัสเพื่อความปลอดภัย ใครก็ตามที่มีสตริงที่เข้ารหัสสามารถถอดรหัสได้ จุดประสงค์คือความปลอดภัยในการส่งข้อมูล: HTTP header, JSON payload, เอกสาร XML และเนื้อหาอีเมล เป็นโปรโตคอลที่ใช้ข้อความซึ่งไม่สามารถรับส่งไบต์ไบนารีดิบได้โดยไม่เกิดความเสียหาย กรณีการใช้งานใน Java ที่พบบ่อย ได้แก่ HTTP Basic Authentication, การฝัง PEM certificate, การเก็บข้อมูลไบนารีในคอลัมน์ข้อความของฐานข้อมูล และการสร้าง JWT token segment

Before · text
After · text
deploy-svc:sk_live_4eC39HqLyjWDarjtT1zdp7dc
ZGVwbG95LXN2Yzpza19saXZlXzRlQzM5SHFMeWpXRGFyanRUMXpkcDdkYw==

Base64.getEncoder().encodeToString() — API มาตรฐาน

java.util.Base64 เปิดตัวใน Java 8 เป็นตัวแทนอย่างเป็นทางการของ sun.misc.BASE64Encoderคลาสนี้มีเมธอด factory แบบ static สามตัว — แต่ละตัวคืนค่า instance ของ Base64.Encoder nested class — ครอบคลุม Base64 สามรูปแบบที่กำหนดใน RFC 4648 ไม่ต้องใช้ไลบรารีของบุคคลที่สาม ไม่ต้อง Maven dependency เพียง import และเรียกใช้เท่านั้น

ตัวอย่างขั้นต่ำ — เข้ารหัสสตริง

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class EncodeDemo {
    public static void main(String[] args) {
        String credentials = "monitoring-svc:9f2a7c4e-b1d8-4a3f";
        byte[] credentialBytes = credentials.getBytes(StandardCharsets.UTF_8);

        String encoded = Base64.getEncoder().encodeToString(credentialBytes);
        System.out.println(encoded);
        // bW9uaXRvcmluZy1zdmM6OWYyYTdjNGUtYjFkOC00YTNm
    }
}

ขั้นตอนสำคัญที่นักพัฒนา Java มักพลาดในครั้งแรก: ต้องแปลง String เป็น byte[] ก่อนเข้ารหัส Base64 ทำงานกับไบต์ ไม่ใช่ตัวอักษร encodeToString() รับ byte[] และคืนค่า Base64 String โดยตรง หากต้องการผลลัพธ์ที่เข้ารหัสเป็นไบต์แทน ให้ใช้ encode(byte[]) — ซึ่งคืนค่า byte[] ของอักขระ Base64 ที่เข้ารหัสเป็น ASCII มีประโยชน์เมื่อเขียนลง OutputStream โดยตรง หรือสร้าง binary protocol frame

HTTP Basic Auth — กรณีการใช้งานที่พบบ่อยที่สุด

HTTP Basic Authentication น่าจะเป็นเหตุผลหลักที่นักพัฒนา Java ต้องใช้การเข้ารหัส Base64 ข้อกำหนด (RFC 7617) กำหนดให้สตริง credentials username:password ต้องถูกเข้ารหัส Base64 และวางไว้ใน Authorization header เคยเห็นการทำผิดวิธีนี้หลายครั้ง — มักเกิดจากลืมใส่ตัวคั่น colon หรือเข้ารหัสส่วนประกอบแยกกัน

Java — HTTP Basic Auth header
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class BasicAuthExample {
    public static void main(String[] args) throws Exception {
        String username = "metrics-exporter";
        String apiKey = "sk_live_4eC39HqLyjWDarjtT1zdp7dc";

        // username:password → Base64
        String credentials = username + ":" + apiKey;
        String authHeader = "Basic " + Base64.getEncoder()
            .encodeToString(credentials.getBytes(StandardCharsets.UTF_8));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.example.com/v2/metrics"))
            .header("Authorization", authHeader)
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());  // 200
    }
}

Round-Trip — เข้ารหัสและถอดรหัส

Java 8+ — encode and decode round-trip
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class RoundTrip {
    public static void main(String[] args) {
        String original = "X-Correlation-ID: req_8a4f2c91-e7b3-4d56-9012-3f7a8b9c0d1e";

        // เข้ารหัส
        String encoded = Base64.getEncoder()
            .encodeToString(original.getBytes(StandardCharsets.UTF_8));
        System.out.println(encoded);
        // WC1Db3JyZWxhdGlvbi1JRDogcmVxXzhhNGYyYzkxLWU3YjMtNGQ1Ni05MDEyLTNmN2E4YjljMGQxZQ==

        // ถอดรหัส
        byte[] decodedBytes = Base64.getDecoder().decode(encoded);
        String decoded = new String(decodedBytes, StandardCharsets.UTF_8);

        System.out.println(original.equals(decoded));  // true
    }
}
หมายเหตุ:API java.util.Base64 เหมือนกันทุกประการตั้งแต่ Java 8 ถึง Java 17 และ Java 21 ไม่จำเป็นต้อง migrate เมื่ออัปเกรด JDK โค้ดเดียวกัน คอมไพล์และรันได้ทุกเวอร์ชันตั้งแต่ Java 8

การเข้ารหัสข้อมูลที่ไม่ใช่สตริง — byte[], UUID และ Timestamp

การเข้ารหัส Base64 ใน Java เริ่มต้นด้วย byte[] เสมอ สตริงแปลงผ่าน getBytes(StandardCharsets.UTF_8), แต่ประเภทอื่นต้องแปลงก่อน UUID, timestamp และตัวระบุตัวเลข ต้องถูก serialize เป็นสตริงหรือ byte ก่อนจึงจะเข้ารหัส Base64 ได้

UUID — เข้ารหัสในรูปแบบสตริง

Java — Base64 encoding a UUID
import java.util.Base64;
import java.util.UUID;
import java.nio.charset.StandardCharsets;

UUID sessionId = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
String encoded = Base64.getEncoder()
    .encodeToString(sessionId.toString().getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// NmJhN2I4MTAtOWRhZC0xMWQxLTgwYjQtMDBjMDRmZDQzMGM4

Compact UUID — เข้ารหัสด้วย 16 ไบต์ดิบ

หากต้องการผลลัพธ์ที่สั้นกว่า ให้แยก 128 บิตของ UUID เป็น 16 ไบต์ดิบ แทนการแปลงเป็นสตริง 36 ตัวอักษร ผลลัพธ์ Base64 จะลดลงจาก 48 ตัวอักษรเหลือ 24 ตัวอักษร

Java — compact UUID encoding
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.UUID;

UUID eventId = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");

ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(eventId.getMostSignificantBits());
buffer.putLong(eventId.getLeastSignificantBits());

String compact = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(buffer.array());
System.out.println(compact);
// VQ6EAOKbQdSnFkRmVUQAAA
// 22 ตัวอักษร เทียบกับ 48 ตัวอักษรสำหรับวิธีแบบสตริง

Timestamp และ Payload ผสม

Java — encoding a JSON-like payload with timestamp
import java.time.Instant;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// จำลอง payload แบบ JWT
String payload = String.format(
    "{"sub":"usr_7b3c","iss":"auth.internal","iat":%d,"exp":%d}",
    Instant.now().getEpochSecond(),
    Instant.now().plusSeconds(3600).getEpochSecond()
);

String encoded = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(payload.getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// eyJzdWIiOiJ1c3JfN2IzYyIsImlzcyI6ImF1dGguaW50ZXJuYWwiLCJpYXQiOj... (URL-safe ไม่มี padding)
คำเตือน:อย่าเรียก toString() บน byte[] แล้วคาดหวังว่าจะได้เนื้อหา — นั่นจะให้ identity hash ของอาร์เรย์เช่น [B@6d06d69c แทน ใช้ new String(bytes, StandardCharsets.UTF_8) หรือส่ง อาร์เรย์ไบต์โดยตรงไปยัง encodeToString()

อ้างอิงเมธอดของ Base64.Encoder

คลาส java.util.Base64 เปิดเผยเมธอด factory สามตัว แต่ละตัวคืนค่า Base64.Encoder ที่กำหนดค่าสำหรับรูปแบบเฉพาะ instance ของ encoder เป็น thread-safe และไม่มี state — สร้างครั้งเดียวและนำกลับมาใช้ซ้ำได้

เมธอด
ประเภท
คำอธิบาย
getEncoder()
Base64.Encoder
คืนค่า encoder มาตรฐานตาม RFC 4648 ที่ใช้ตัวอักษรพื้นฐาน (A-Z, a-z, 0-9, +, /)
getUrlEncoder()
Base64.Encoder
คืนค่า encoder ที่ใช้ตัวอักษรแบบ URL-safe (- แทน +, _ แทน /)
getMimeEncoder()
Base64.Encoder
คืนค่า MIME encoder ที่แทรกการขึ้นบรรทัดใหม่ \r\n ทุก 76 ตัวอักษร
getMimeEncoder(lineLength, lineSeparator)
Base64.Encoder
MIME encoder ที่กำหนดความยาวบรรทัดและไบต์ตัวคั่นเองได้
encoder.withoutPadding()
Base64.Encoder
คืนค่า encoder ที่ไม่ใส่อักขระเติม = ท้ายสตริง
encoder.encode(byte[])
byte[]
เข้ารหัสอาร์เรย์ไบต์ คืนค่าเป็นอาร์เรย์ไบต์ที่เข้ารหัสแล้ว
encoder.encodeToString(byte[])
String
เข้ารหัสอาร์เรย์ไบต์ คืนค่าเป็น String โดยตรง
encoder.wrap(OutputStream)
OutputStream
ห่อ OutputStream สำหรับการเข้ารหัส Base64 แบบสตรีม

Base64.getUrlEncoder() — การเข้ารหัสแบบ URL-Safe

URL-safe encoder ใช้ตัวอักษรสลับที่ + กลายเป็น - และ / กลายเป็น _, ตามที่กำหนดใน RFC 4648 Section 5 สิ่งนี้มีความสำคัญเมื่อสตริง Base64 ปรากฏใน URL query parameter, ชื่อไฟล์ หรือค่า cookie — อักขระ Base64 มาตรฐานขัดแย้งกับ ตัวคั่น URL และอักขระสงวนของระบบไฟล์

Java — URL-safe Base64 encoding
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String redirectUri = "https://app.internal/callback?state=auth_pending&nonce=9f2a7c";
byte[] data = redirectUri.getBytes(StandardCharsets.UTF_8);

// encoder มาตรฐาน — มี + และ / ซึ่งทำให้ URL เสียหาย
String standard = Base64.getEncoder().encodeToString(data);
System.out.println(standard);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s/c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// URL-safe encoder — ปลอดภัยสำหรับ query parameter และชื่อไฟล์
String urlSafe = Base64.getUrlEncoder().encodeToString(data);
System.out.println(urlSafe);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// URL-safe ไม่มี padding — สำหรับ JWT และ token แบบกระชับ
String noPadding = Base64.getUrlEncoder().withoutPadding().encodeToString(data);
System.out.println(noPadding);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw

รูปแบบ withoutPadding() ตัดอักขระ = ท้ายสตริงออก ข้อกำหนด JWT กำหนดให้ใช้ Base64 แบบ URL-safe ที่ไม่มี padding สำหรับส่วน header และ payload ดังนั้น getUrlEncoder().withoutPadding() คือการเรียกที่ต้องการเมื่อสร้างหรือจัดการ JWT token ด้วยตนเอง

หมายเหตุ:เมธอด withoutPadding() คืนค่า encoder instance ใหม่ — ไม่แก้ไข instance เดิม ทั้งสองสามารถกำหนดให้กับฟิลด์ static final และนำกลับมาใช้ซ้ำข้ามเธรดได้อย่างปลอดภัย

การเข้ารหัสจากไฟล์และ API Response

สองสถานการณ์จริงที่พบบ่อยที่สุดสำหรับการเข้ารหัส Base64 ใน Java: การอ่านไฟล์ไบนารีจากดิสก์ (certificate, รูปภาพ, configuration bundle) และการเข้ารหัสข้อมูลที่ได้รับจาก HTTP response

เข้ารหัสไฟล์เป็น Base64

Java — encoding a file
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

public class FileEncoder {
    public static void main(String[] args) {
        try {
            byte[] fileBytes = Files.readAllBytes(Path.of("certs/server.pem"));
            String encoded = Base64.getEncoder().encodeToString(fileBytes);

            System.out.printf("Original: %d bytes%n", fileBytes.length);
            System.out.printf("Encoded:  %d chars%n", encoded.length());

            // เขียนเนื้อหาที่เข้ารหัสลงไฟล์ข้อความ
            Files.writeString(
                Path.of("certs/server.pem.b64"),
                encoded
            );
        } catch (java.io.IOException e) {
            System.err.println("Failed to read file: " + e.getMessage());
        }
    }
}

เข้ารหัส API Response Body

Java 11+ — encoding an HTTP response
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

public class ApiEncoder {
    public static void main(String[] args) {
        try {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.example.com/v2/reports/weekly.pdf"))
                .header("Authorization", "Bearer tok_8f2a9c3d")
                .build();

            HttpResponse<byte[]> response = client.send(
                request, HttpResponse.BodyHandlers.ofByteArray()
            );

            if (response.statusCode() == 200) {
                String encoded = Base64.getEncoder()
                    .encodeToString(response.body());
                System.out.printf("Encoded %d bytes → %d chars%n",
                    response.body().length, encoded.length());
            } else {
                System.err.printf("HTTP %d: %s%n",
                    response.statusCode(),
                    new String(response.body()));
            }
        } catch (Exception e) {
            System.err.println("Request failed: " + e.getMessage());
        }
    }
}

หมายเหตุก่อนส่วน CLI: หากต้องการวางไฟล์หรือ API response แล้วรับผลลัพธ์ Base64 โดยไม่ต้องเขียนโค้ด Base64 Encoder ออนไลน์ รองรับทั้งข้อความและ binary input

การเข้ารหัส Base64 ผ่าน Command-Line

บางครั้งต้องการเข้ารหัสสตริงหรือไฟล์จาก terminal เท่านั้น — ไม่มีโปรเจกต์ Java, ไม่มี IDE, ไม่มีขั้นตอน build ระบบ Unix ส่วนใหญ่มาพร้อมคำสั่ง base64 และหากติดตั้ง JDK ไว้สามารถใช้ jshell สำหรับวิธีแบบ Java native ได้

Bash — command-line Base64 encoding
# macOS / Linux — เข้ารหัสสตริง
echo -n "deploy-bot:sk_prod_9f2a7c4e" | base64
# ZGVwbG95LWJvdDpza19wcm9kXzlmMmE3YzRl

# เข้ารหัสไฟล์
base64 < certs/server.pem > certs/server.pem.b64

# ใช้ jshell (JDK 9+)
echo 'System.out.println(java.util.Base64.getEncoder().encodeToString("deploy-bot:sk_prod_9f2a7c4e".getBytes()))' | jshell -

# ใช้ java โดยตรงด้วย one-liner
java -e 'System.out.println(java.util.Base64.getEncoder().encodeToString(args[0].getBytes()))' "my-secret"
# หมายเหตุ: java -e ต้องใช้ JDK 23+ (JEP 477)

วิธี jshell มีประโยชน์โดยเฉพาะเมื่อต้องการยืนยันว่าโค้ด Java สร้างผลลัพธ์เดียวกันกับ Unix tool หรือเมื่อดีบักความไม่ตรงกันระหว่างสิ่งที่ service ส่งออกกับสิ่งที่ผู้รับคาดหวัง มีประโยชน์มากพอที่จะตั้ง shell alias ไว้

หมายเหตุ:บน macOS คำสั่ง base64 ใช้ -D สำหรับการถอดรหัส บน Linux (GNU coreutils) ใช้-d พฤติกรรมการเข้ารหัสเหมือนกันทั้งสองระบบ แฟล็ก -w 0 บน Linux ปิดการตัดบรรทัดในผลลัพธ์ ซึ่งมักเป็นสิ่งที่ต้องการเมื่อ pipe ไปยังคำสั่งอื่น

Apache Commons Codec — ทางเลือกประสิทธิภาพสูง

สำหรับแอปพลิเคชันส่วนใหญ่ java.util.Base64 มีประสิทธิภาพเพียงพอ แต่หากต้องประมวลผลการเข้ารหัสหลายล้านครั้งในลูปแน่นๆ — เช่น log ingestion pipeline หรือ message broker ที่มี throughput สูง — Apache Commons Codec คุ้มค่าแก่การทดสอบ benchmark มีมาก่อน Java 8 และให้ทางเลือกที่ผ่านการพิสูจน์แล้ว พร้อม API surface ที่แตกต่างออกไปเล็กน้อย

Java — Apache Commons Codec
// Maven: org.apache.commons:commons-codec:1.17.0
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;

byte[] telemetryPayload = ("{"service":"metrics-collector","
    + ""host":"prod-east-07","
    + ""cpu_pct":72.4,"
    + ""mem_mb":3891,"
    + ""timestamp":1710523200}")
    .getBytes(StandardCharsets.UTF_8);

// การเข้ารหัสมาตรฐาน
String encoded = Base64.encodeBase64String(telemetryPayload);

// การเข้ารหัสแบบ URL-safe
String urlSafe = Base64.encodeBase64URLSafeString(telemetryPayload);

// ตรวจสอบว่าสตริงเป็น Base64 ที่ถูกต้อง
boolean valid = Base64.isBase64(encoded);
System.out.println(valid);  // true

Apache Commons Codec ยังมี Base64OutputStream และ Base64InputStream สำหรับสถานการณ์การสตรีม และมีเมธอด validation ที่ JDK encoder ไม่มี หาก Commons Codec อยู่ใน dependency tree อยู่แล้ว (มาพร้อมกับโปรเจกต์ Apache หลายตัว) ไม่มีเหตุผลที่จะไม่ใช้

Guava BaseEncoding

ไลบรารี Guava ของ Google มี BaseEncoding ซึ่งให้ fluent API สำหรับ Base64 พร้อมตัวคั่นบรรทัดที่กำหนดได้, การควบคุม padding และรองรับทั้งตัวอักษรมาตรฐานและ URL-safe API อ่านง่าย แต่การเพิ่ม Guava (ประมาณ 3 MB) เพียงเพื่อการเข้ารหัส Base64 นั้นเกินความจำเป็น หาก Guava อยู่ในโปรเจกต์แล้ว สำหรับ collection หรือ caching utility encoding API เป็น bonus ที่ดี

Java — Guava BaseEncoding
// Maven: com.google.guava:guava:33.1.0-jre
import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;

byte[] webhookPayload = ("{"event":"deployment.completed","
    + ""repo":"payments-api","
    + ""sha":"a7f2c91e4b3d","
    + ""environment":"production"}")
    .getBytes(StandardCharsets.UTF_8);

// Base64 มาตรฐาน
String standard = BaseEncoding.base64().encode(webhookPayload);

// URL-safe
String urlSafe = BaseEncoding.base64Url().encode(webhookPayload);

// ไม่มี padding
String noPad = BaseEncoding.base64Url().omitPadding().encode(webhookPayload);

// ใส่ตัวคั่นบรรทัด (แบบ PEM)
String wrapped = BaseEncoding.base64()
    .withSeparator("\n", 64)
    .encode(webhookPayload);

Base64.getMimeEncoder() — ผลลัพธ์แบบ MIME และ PEM ที่ตัดบรรทัด

MIME encoder แทรกการขึ้นบรรทัดใหม่ \r\n ทุก 76 ตัวอักษร ตามข้อกำหนด MIME (RFC 2045) PEM certificate, S/MIME email attachment และ API รุ่นเก่าบางตัวคาดหวังรูปแบบนี้ encoder มาตรฐานและ URL-safe สร้างบรรทัดเดียวที่ไม่ขาด — หากส่งผลลัพธ์ไปยังระบบที่คาดหวัง Base64 แบบตัดบรรทัด อาจเกิดความล้มเหลวแบบเงียบหรือปฏิเสธข้อมูล

Java — MIME Base64 encoding
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// จำลอง PEM certificate body
byte[] certData = new byte[256];  // ในทางปฏิบัติ อ่านจากไฟล์ .der
new java.security.SecureRandom().nextBytes(certData);

// MIME encoder เริ่มต้น — 76 ตัวอักษรต่อบรรทัด, ตัวคั่น \r\n
String mimeEncoded = Base64.getMimeEncoder().encodeToString(certData);
System.out.println(mimeEncoded);
// QYx2K3p8Xg7JmN1R+wFkLd...  (76 ตัวอักษร)
// Ht5Bv9CzAq0PnSjYl8WxUe...  (76 ตัวอักษร)
// ...

// MIME encoder กำหนดเอง — 64 ตัวอักษรต่อบรรทัด (มาตรฐาน PEM), ตัวคั่น \n
Base64.Encoder pemEncoder = Base64.getMimeEncoder(64, new byte[]{'\n'});
String pemBody = pemEncoder.encodeToString(certData);
System.out.println("-----BEGIN CERTIFICATE-----");
System.out.println(pemBody);
System.out.println("-----END CERTIFICATE-----");
คำเตือน:อย่าใช้ getMimeEncoder() สำหรับ JWT token, HTTP header หรือ URL parameter การขึ้นบรรทัดใหม่จะทำให้ข้อมูลเสียหายในบริบทเหล่านั้น ใช้ getEncoder() หรือ getUrlEncoder() แทน

การสตรีมไฟล์ขนาดใหญ่ด้วย Base64.getEncoder().wrap()

การโหลดทั้งไฟล์เป็น byte[] ด้วย Files.readAllBytes() ได้ผลดีกับไฟล์เล็ก แต่สำหรับไฟล์ที่ใหญ่กว่า 50-100 MB เสี่ยงต่อ OutOfMemoryErrorJDK มี Base64.getEncoder().wrap(OutputStream), ซึ่งคืนค่า OutputStream ที่เข้ารหัสข้อมูลแบบ on-the-fly ขณะที่เขียนลงไป ไบต์ที่เข้ารหัสแล้วไหลผ่านไปยัง stream รองรับโดยไม่ต้องบัฟเฟอร์ทั้ง input

Java — streaming Base64 encoding
import java.io.*;
import java.nio.file.*;
import java.util.Base64;

public class StreamingEncoder {
    public static void main(String[] args) throws IOException {
        Path inputPath = Path.of("backups/database-export.sql.gz");
        Path outputPath = Path.of("backups/database-export.sql.gz.b64");

        try (
            InputStream in = Files.newInputStream(inputPath);
            OutputStream fileOut = Files.newOutputStream(outputPath);
            OutputStream base64Out = Base64.getEncoder().wrap(fileOut)
        ) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            long totalBytes = 0;

            while ((bytesRead = in.read(buffer)) != -1) {
                base64Out.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            System.out.printf("Streamed %d bytes through Base64 encoder%n", totalBytes);
        }
        // การปิด base64Out จะ flush ไบต์ padding สุดท้ายโดยอัตโนมัติ
    }
}

บล็อก try-with-resources จัดการการ flush และปิด มีรายละเอียดหนึ่งที่มักสร้างปัญหา: padding สุดท้ายของ Base64 จะถูกเขียนเมื่อ OutputStream ที่ครอบไว้ถูกปิดเท่านั้น หากลืมปิด (หรือปิดเฉพาะ stream ด้านนอก) อักขระสุดท้ายสองสามตัวของผลลัพธ์ที่เข้ารหัสอาจหายไป

การสตรีมไปยัง Network Socket

เมธอด wrap() ทำงานกับ OutputStream ใดก็ได้ — file output, socket output, HTTP response body แม้แต่ ByteArrayOutputStreamตัวอย่างการเขียนข้อมูลที่เข้ารหัส Base64 โดยตรงลงใน in-memory buffer มีประโยชน์สำหรับ unit testing หรือสร้าง payload ที่จะส่งผ่าน HTTP:

Java — streaming to ByteArrayOutputStream
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

try (OutputStream encoder = Base64.getEncoder().wrap(buffer)) {
    // เขียนข้อมูลเป็น chunk — จำลองการอ่านจาก stream
    encoder.write("chunk-1:telemetry-data-".getBytes(StandardCharsets.UTF_8));
    encoder.write("chunk-2:more-payload-".getBytes(StandardCharsets.UTF_8));
    encoder.write("chunk-3:final-segment".getBytes(StandardCharsets.UTF_8));
}

String encoded = buffer.toString(StandardCharsets.UTF_8);
System.out.println(encoded);
// Y2h1bmstMTp0ZWxlbWV0cnktZGF0YS1jaHVuay0yOm1vcmUtcGF5bG9hZC1jaHVuay0zOmZpbmFsLXNlZ21lbnQ=

// ยืนยัน round-trip
byte[] decoded = Base64.getDecoder().decode(encoded);
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// chunk-1:telemetry-data-chunk-2:more-payload-chunk-3:final-segment
หมายเหตุ:ขนาด buffer ในตัวอย่างการสตรีม (8192 ไบต์) ไม่ใช่การสุ่ม ตรงกับขนาด buffer เริ่มต้น ที่ BufferedInputStream ใช้ และเป็นจุดสมดุลที่ดีระหว่าง การใช้หน่วยความจำและค่าใช้จ่าย system call Buffer เล็กกว่าเพิ่มจำนวนการเรียก read/write; buffer ใหญ่กว่าสิ้นเปลือง memory โดยไม่ได้ throughput ที่ดีขึ้นอย่างมีนัยสำคัญ

Encoder Instance แบบ Thread-Safe — เก็บและนำกลับมาใช้ซ้ำ

Base64.Encoder ที่คืนค่าจากเมธอด factory เป็น immutable และ thread-safe การเรียก Base64.getEncoder() ทุกครั้งสร้าง object ใหม่ JVM อาจ optimize สิ่งนี้ออกได้ แต่การเก็บ encoder ไว้ใน ฟิลด์ static final ทำให้ intent ชัดเจนและหลีกเลี่ยงการ allocate ที่ไม่จำเป็นใน hot path

Java — reusable encoder instances
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class TokenService {
    // สร้างครั้งเดียว ใช้ได้ทุกที่ — thread-safe
    private static final Base64.Encoder STANDARD = Base64.getEncoder();
    private static final Base64.Encoder URL_SAFE = Base64.getUrlEncoder().withoutPadding();
    private static final Base64.Encoder MIME = Base64.getMimeEncoder();

    public static String encodeForHeader(String value) {
        return STANDARD.encodeToString(value.getBytes(StandardCharsets.UTF_8));
    }

    public static String encodeForUrl(byte[] data) {
        return URL_SAFE.encodeToString(data);
    }

    public static String encodeForEmail(byte[] attachment) {
        return MIME.encodeToString(attachment);
    }
}

pattern นี้มีประโยชน์โดยเฉพาะใน Spring Boot service ที่คลาส utility จัดการ encoding ข้ามหลาย controller หรือ service method การเรียก withoutPadding() คืนค่า encoder instance ใหม่ จึงสามารถเก็บทั้งรูปแบบที่มีและไม่มี padding เป็นฟิลด์แยกกัน การเรียก encodeToString() หรือ encode() แต่ละครั้งเป็น stateless — ไม่ต้อง synchronize ไม่มี shared mutable state

ข้อผิดพลาดที่พบบ่อย

เรียก getBytes() โดยไม่ระบุ charset

ปัญหา: String.getBytes() ที่ไม่มี charset argument ใช้ encoding เริ่มต้นของแพลตฟอร์ม ซึ่งเป็น windows-1252 บน Windows, UTF-8 บน Linux ส่วนใหญ่ และต่างกันบน macOS โค้ดเดียวกันสร้างผลลัพธ์ Base64 ต่างกันบนเครื่องต่างกัน

วิธีแก้: ระบุ StandardCharsets.UTF_8 อย่างชัดเจนเสมอ

Before · Java
After · Java
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes();  // platform default — ไม่แน่นอน
String encoded = Base64.getEncoder().encodeToString(bytes);
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(bytes);
ใช้ standard encoder สำหรับ URL parameter

ปัญหา: Base64.getEncoder() สร้างอักขระ + และ / เมื่อวางใน URL query string, + จะถูกตีความเป็น space และ / เป็น path separator ทำให้ค่าเสียหายแบบเงียบที่ฝั่งรับ

วิธีแก้: ใช้ Base64.getUrlEncoder() สำหรับทุกค่าที่จะปรากฏใน URL

Before · Java
After · Java
// Token ใน URL query parameter — จะพัง
String token = Base64.getEncoder()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
// URL-safe encoding — ไม่มีอักขระ + หรือ /
String token = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
ถอดรหัสด้วย encoder variant ผิด

ปัญหา: การเข้ารหัสด้วย getUrlEncoder() แล้วถอดรหัสด้วย getDecoder() (หรือกลับกัน) จะ throw IllegalArgumentException เพราะ - และ _ ไม่ถูกต้องในตัวอักษร Base64 มาตรฐาน และ + กับ / ไม่ถูกต้องในตัวอักษร URL-safe

วิธีแก้: ถอดรหัสด้วย decoder ที่ตรงกันเสมอ: getUrlDecoder() สำหรับ URL-safe, getDecoder() สำหรับมาตรฐาน

Before · Java
After · Java
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// ภายหลัง...
byte[] decoded = Base64.getDecoder()  // decoder ผิด
    .decode(encoded);
// IllegalArgumentException ถ้า encoded มี - หรือ _
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// ภายหลัง...
byte[] decoded = Base64.getUrlDecoder()  // decoder ที่ตรงกัน
    .decode(encoded);
ไม่ปิด wrap() OutputStream

ปัญหา: streaming encoder บัฟเฟอร์ input ไว้สูงสุด 2 ไบต์รอกลุ่ม 3 ไบต์ที่ครบ หากไม่ปิด OutputStream ที่ครอบไว้ อักขระ Base64 สุดท้าย 1-4 ตัว (รวมถึง padding) จะไม่ถูกเขียน

วิธีแก้: ใช้ try-with-resources หรือเรียก close() บน wrapped stream อย่างชัดเจนก่อนอ่านผลลัพธ์

Before · Java
After · Java
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = Base64.getEncoder().wrap(baos);
b64os.write(data);
// baos.toString() ไม่ครบ — ขาดไบต์สุดท้าย
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (OutputStream b64os = Base64.getEncoder().wrap(baos)) {
    b64os.write(data);
}  // close() flush padding สุดท้าย
String encoded = baos.toString();  // ครบถ้วน

เปรียบเทียบวิธีการเข้ารหัส Base64

เมธอด
URL-Safe
Streaming
ขึ้นบรรทัดใหม่
ประเภทกำหนดเอง
ต้องติดตั้งเพิ่ม
Base64.getEncoder()
✓ (wrap)
ไม่ (JDK 8+)
Base64.getUrlEncoder()
✓ (wrap)
ไม่ (JDK 8+)
Base64.getMimeEncoder()
✓ (wrap)
✓ (76 chars)
ไม่ (JDK 8+)
Apache Commons Codec
Maven dependency
Guava BaseEncoding
✓ (กำหนดได้)
Maven dependency
jcmd / CLI base64
✓ (pipe)
N/A
ติดตั้งในระบบ

สำหรับโปรเจกต์ส่วนใหญ่: java.util.Base64 คือตัวเลือกที่ถูกต้อง ไม่มี dependency, ติดมากับ JDK, thread-safe และครอบคลุม RFC 4648 ทั้งสามรูปแบบ เลือก Apache Commons Codec เฉพาะเมื่ออยู่ใน classpath อยู่แล้ว และต้องการเมธอด isBase64() หรือ streaming Base64OutputStream BaseEncoding ของ Guava เป็นตัวเลือกที่เหมาะสมหากโปรเจกต์ใช้ Guava อยู่แล้ว แต่การเพิ่ม dependency ขนาด 3 MB เพียงเพื่อ Base64 นั้นยากที่จะ justify

สามสถานการณ์, สามตัวเลือก: web service มาตรฐานที่ต้องการ Basic Auth หรือ JWT? ใช้ JDK โปรเจกต์รุ่นเก่าที่ดึง Commons Codec ผ่าน Spring หรือ Apache HTTP Client? ใช้เลย — ไม่มีเหตุผลที่จะมีไลบรารี Base64 สองตัวใน classpath โปรเจกต์ที่ใช้ Guava สำหรับ caching และ collection? ใช้ BaseEncoding สำหรับ fluent API ที่สะอาดตา ไม่ควรเพิ่มไลบรารีเพียงเพื่อการเข้ารหัส Base64 — JDK version ดีพอแล้วตั้งแต่ปี 2014

หากต้องการยืนยันผลลัพธ์ที่เข้ารหัสอย่างรวดเร็วโดยไม่รัน Java code วางลงใน Base64 Encoder เพื่อยืนยันว่าผลลัพธ์ตรงกับที่โค้ดสร้าง

คำถามที่พบบ่อย

วิธีเข้ารหัส Base64 สตริงใน Java ทำอย่างไร?

แปลงสตริงเป็นไบต์ก่อนด้วย getBytes(StandardCharsets.UTF_8) แล้วส่งอาร์เรย์ไบต์ไปยัง Base64.getEncoder().encodeToString() ต้องระบุ UTF-8 อย่างชัดเจนเสมอ — การเรียก getBytes() โดยไม่ระบุ charset จะใช้ค่าเริ่มต้นของแพลตฟอร์ม ซึ่งต่างกันในแต่ละระบบปฏิบัติการและการกำหนดค่า JVM

Java
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String payload = "grant_type=client_credentials&scope=read:metrics";
String encoded = Base64.getEncoder()
    .encodeToString(payload.getBytes(StandardCharsets.UTF_8));
// Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmc2NvcGU9cmVhZDptZXRyaWNz

Base64.getEncoder() กับ Base64.getUrlEncoder() ต่างกันอย่างไร?

ทั้งสองเข้ารหัสเป็น Base64 แต่ getUrlEncoder() ใช้ตัวอักษรแบบ URL-safe ตาม RFC 4648 Section 5 โดยแทน + ด้วย - และ / ด้วย _ เพื่อให้ผลลัพธ์ปรากฏใน URL และชื่อไฟล์ได้โดยไม่ต้อง percent-encode encoder มาตรฐานใช้ + และ / ซึ่งขัดแย้งกับพารามิเตอร์ query ของ URL และ path segment

Java
byte[] data = "subject=usr_7b3c&role=admin".getBytes(StandardCharsets.UTF_8);

String standard = Base64.getEncoder().encodeToString(data);
// c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu

String urlSafe = Base64.getUrlEncoder().encodeToString(data);
// c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu
// (เหมือนกันในที่นี้ แต่จะแทน + → - และ / → _ เมื่ออักขระเหล่านั้นปรากฏ)

java.util.Base64 ใน Java 8 กับ Java 17 เหมือนกันไหม?

ใช่ API java.util.Base64 ไม่มีการเปลี่ยนแปลงตั้งแต่เปิดตัวใน Java 8 คลาส nested Encoder และ Decoder รวมถึงเมธอด factory ทั้งหมด (getEncoder, getUrlEncoder, getMimeEncoder) เหมือนกันทุกประการใน Java 8, 11, 17 และ 21 ไม่จำเป็นต้อง migrate โค้ดเมื่ออัปเกรด JDK

Java
// โค้ดนี้คอมไพล์และรันได้เหมือนกันบน Java 8 ถึง Java 21+
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String encoded = Base64.getEncoder()
    .encodeToString("stable-api".getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);  // c3RhYmxlLWFwaQ==

วิธีเข้ารหัสไฟล์เป็น Base64 ใน Java ทำอย่างไร?

อ่านไฟล์เป็นอาร์เรย์ไบต์ด้วย Files.readAllBytes(Path) แล้วส่งไปยัง Base64.getEncoder().encodeToString() สำหรับไฟล์ขนาดใหญ่ที่ไม่ควรโหลดทั้งหมดเข้าหน่วยความจำ ให้ใช้ Base64.getEncoder().wrap(OutputStream) เพื่อสตรีมผลลัพธ์ที่เข้ารหัส

Java
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;

byte[] fileBytes = Files.readAllBytes(Path.of("config/tls-cert.pem"));
String encoded = Base64.getEncoder().encodeToString(fileBytes);

ทำไม sun.misc.BASE64Encoder จึงถูก deprecated?

sun.misc.BASE64Encoder เป็นคลาสภายในของ JDK ที่ไม่เคยเป็นส่วนหนึ่งของ public API อยู่ใน package sun.misc ซึ่ง Oracle เตือนไม่ให้ใช้อย่างชัดเจน Java 8 เปิดตัว java.util.Base64 เป็นตัวแทนอย่างเป็นทางการที่รองรับ public API ตั้งแต่ Java 9 และระบบ module การเข้าถึงคลาส sun.misc จะทำให้เกิดคำเตือนหรือข้อผิดพลาดขึ้นอยู่กับการกำหนดค่า JDK

Java
// วิธีเก่า — ห้ามใช้ ถูกลบออกใน JDK เวอร์ชันใหม่
// import sun.misc.BASE64Encoder;
// String encoded = new BASE64Encoder().encode(data);

// วิธีที่ถูกต้องตั้งแต่ Java 8
import java.util.Base64;
String encoded = Base64.getEncoder().encodeToString(data);

วิธีทำ round-trip เข้ารหัสและถอดรหัส Base64 ใน Java ทำอย่างไร?

เข้ารหัสด้วย Base64.getEncoder().encodeToString(bytes) และถอดรหัสด้วย Base64.getDecoder().decode(encodedString) แปลงอาร์เรย์ไบต์ที่ถอดรหัสกลับเป็น String ด้วย new String(bytes, StandardCharsets.UTF_8) การทำ round-trip จะรักษาข้อมูลต้นฉบับไว้ครบถ้วน ตราบใดที่ใช้ charset เดียวกันสำหรับทั้ง getBytes() และ new String()

Java
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// เข้ารหัส
String original = "session_token=eyJhbGciOiJSUzI1NiJ9";
byte[] originalBytes = original.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(originalBytes);

// ถอดรหัส
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes, StandardCharsets.UTF_8);

System.out.println(original.equals(decoded));  // true

เครื่องมือที่เกี่ยวข้อง

  • Base64 Decoderถอดรหัสสตริง Base64 กลับเป็นข้อความหรือข้อมูลไบนารีต้นฉบับ — เป็นการดำเนินการผกผันของการเข้ารหัส
  • URL EncoderPercent-encode สตริงสำหรับใช้งานใน URL — ต่างจากการเข้ารหัส Base64 แบบ URL-safe แต่มักใช้ร่วมกัน
  • JWT Decoderตรวจสอบ JWT token ที่ส่วน header และ payload เข้ารหัสด้วย Base64url JSON — ถอดรหัสได้โดยไม่ต้องใช้ไลบรารี
  • JSON Formatterจัดรูปแบบ JSON payload ให้อ่านง่ายก่อนหรือหลังการเข้ารหัส Base64 — มีประโยชน์เมื่อดีบัก API integration
มีให้ในภาษาอื่นด้วย:JavaScriptPython
AO
Aisha OseiJava Security & API Engineer

Aisha is a Java engineer specialising in application security, Spring Security, and API design. She has worked on identity and access management systems, OAuth 2.0 integrations, and microservice security at scale. She writes about secure Java coding practices, token validation, cryptographic utilities, and the Spring ecosystem from a security-first perspective.

PN
Pavel Novakผู้ตรวจสอบทางเทคนิค

Pavel is a backend engineer with deep roots in the JVM ecosystem, working primarily with Java and Kotlin. He has extensive experience building data-intensive services and integrating third-party APIs at scale. He writes about modern Java features, the Jackson ecosystem, serialisation patterns, and practical approaches to keeping large codebases maintainable.