JavaでBase64エンコード — 完全ガイド

·Java Security & API Engineer·レビュー担当Pavel Novak·公開日

無料の Base64エンコーダー をブラウザで直接使用 — インストール不要。

Base64エンコーダー をオンラインで試す →

HTTPのBasic認証ヘッダーを組み立てるとき、KubernetesのSecretに証明書を埋め込むとき、 あるいはJSON APIでバイナリデータを送るとき——最初のステップはいつも同じです: 生のバイト列をASCIIセーフな文字列に Base64エンコードすることです。 Javaではこれを java.util.Base64で簡単に実現できます。Java 8以降に標準搭載されたこのAPIは、 非推奨となった sun.misc.BASE64Encoderの公式な後継です。コードを書かずにすぐエンコードしたい場合は、 ToolDeckのBase64エンコーダ がブラウザ上で即座に処理します。 このガイドでは Base64.getEncoder() getUrlEncoder() getMimeEncoder()、 ファイルエンコード、 wrap(OutputStream)によるストリーミング、そして経験豊富なJava開発者でもはまりがちなミスを解説します。 すべてのサンプルコードはJava 8からJava 21+でコンパイル・実行できます。

  • Base64.getEncoder().encodeToString(bytes)が標準の1行コード — Java 8からJDKに内蔵され、Java 17・21でも変更なし。
  • エンコード前にString.getBytes()へは必ずStandardCharsets.UTF_8を渡す — 省略するとJVMごとに異なるプラットフォームデフォルトが使われる。
  • getUrlEncoder()はURLセーフな出力(+の代わりに-、/の代わりに_)を生成し、withoutPadding()で末尾の=を除去できる。
  • getMimeEncoder()は76文字ごとに改行を挿入する — メール(MIME)やPEM証明書フォーマットに必要。
  • 大きなファイルにはBase64.getEncoder().wrap(OutputStream)を使い、ファイル全体をメモリに読み込まずにストリーミングする。

Base64エンコードとは?

Base64は任意のバイナリデータを64種類の印刷可能なASCII文字—— A-Z、a-z、0-9、 + /——で構成された文字列に変換します。 入力3バイトがちょうど4文字のBase64に対応します。入力長が3の倍数でない場合は、 1文字または2文字の = パディングが付加されます。エンコード後のサイズは元のデータより約33%大きくなります。

Base64は暗号化ではありません。エンコードされた文字列があれば誰でもデコードできます。 その目的はトランスポートの安全性にあります。HTTPヘッダー、JSONペイロード、XMLドキュメント、 メール本文はテキストベースのプロトコルであり、生のバイナリをそのまま含めるとデータが壊れる恐れがあります。 Javaでの主な用途としては、HTTP Basic認証、PEM証明書の埋め込み、データベースのテキスト列へのバイナリ保存、 JWTトークンセグメントの構築などがあります。

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

Base64.getEncoder().encodeToString() — 標準API

java.util.Base64 はJava 8で sun.misc.BASE64Encoderの公式な後継として導入されました。 このクラスはRFC 4648で定義された3種類のBase64バリアントに対応した Base64.Encoder ネストクラスのインスタンスをそれぞれ返す、3つの静的ファクトリメソッドを提供します。 サードパーティライブラリは不要です。Maven依存関係も不要です。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[]) を使用してください——これはASCIIエンコードされたBase64文字の byte[] を返し、OutputStreamへの直接書き込みやバイナリプロトコルフレームの構築に役立ちます。

HTTP Basic認証 — 最も一般的なユースケース

HTTP Basic認証はJava開発者がBase64エンコードを必要とする最も一般的な理由です。 仕様(RFC 7617)では username:password という認証情報文字列をBase64エンコードしてAuthorizationヘッダーに設定することが求められています。 コロンのセパレータを忘れたり、各コンポーネントを個別にエンコードしたりといった誤りが後を絶ちません。

Java — HTTP Basic Authヘッダー
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
    }
}

ラウンドトリップ — エンコードとデコード

Java 8+ — エンコード・デコードのラウンドトリップ
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
    }
}
注意:java.util.Base64 APIはJava 8からJava 17・Java 21まで同一です。JDKをアップグレードしても移行は不要で、Java 8以降のどのバージョンでも同じコードがコンパイル・実行されます。

文字列以外のデータのエンコード — byte[]、UUID、タイムスタンプ

JavaでのBase64エンコードは常に byte[]から始まります。 文字列は getBytes(StandardCharsets.UTF_8)で変換しますが、他の型は最初に変換ステップが必要です。UUID、タイムスタンプ、数値IDは Base64エンコードの前に文字列またはバイト表現にシリアライズする必要があります。

UUID — 文字列表現としてエンコード

Java — UUIDのBase64エンコード
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

コンパクトUUID — 生の16バイトとしてエンコード

エンコード結果を短くしたい場合は、UUIDを36文字の文字列に変換する代わりに 128ビットを16バイトの生データとして取り出します。Base64の出力は48文字から24文字に短縮されます。

Java — コンパクトUUIDエンコード
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
// 文字列ベースの方法では48文字 → こちらは22文字

タイムスタンプと複合ペイロード

Java — タイムスタンプを含むJWTスタイルのペイロードのエンコード
import java.time.Instant;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// 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セーフ、パディングなし)
警告:byte[]に対してtoString()を呼び出してもその内容は得られません—— [B@6d06d69cのような識別ハッシュが返るだけです。 new String(bytes, StandardCharsets.UTF_8)を使用するか、 バイト配列を直接encodeToString()に渡してください。

Base64.Encoderメソッドリファレンス

java.util.Base64 クラスは3つのファクトリメソッドを提供しており、それぞれ特定のバリアント用に設定された Base64.Encoder を返します。エンコーダインスタンスはスレッドセーフかつステートレスです—— 一度作成したら再利用できます。

メソッド
説明
getEncoder()
Base64.Encoder
標準アルファベット(A-Z、a-z、0-9、+、/)を使用するRFC 4648準拠の基本エンコーダを返す
getUrlEncoder()
Base64.Encoder
URLセーフアルファベット(+の代わりに-、/の代わりに_)を使用するエンコーダを返す
getMimeEncoder()
Base64.Encoder
76文字ごとに\r\n改行を挿入するMIMEエンコーダを返す
getMimeEncoder(lineLength, lineSeparator)
Base64.Encoder
カスタムの行長とセパレータバイトを持つMIMEエンコーダ
encoder.withoutPadding()
Base64.Encoder
末尾の=パディング文字を省略するエンコーダを返す
encoder.encode(byte[])
byte[]
バイト配列をエンコードし、エンコード済みバイト配列を返す
encoder.encodeToString(byte[])
String
バイト配列をエンコードし、エンコード済みStringを直接返す
encoder.wrap(OutputStream)
OutputStream
ストリーミングBase64エンコード用にOutputStreamをラップする

Base64.getUrlEncoder() — URLセーフエンコード

URLセーフエンコーダはRFC 4648のセクション5で定義された代替アルファベットを使用します。 + - に、 / _ に変換します。Base64文字列がURLのクエリパラメータ、ファイル名、またはCookieの値として現れる場合に重要です—— 標準のBase64文字はURLのデリミタやファイルシステムの予約文字と競合します。

Java — URLセーフBase64エンコード
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);

// 標準エンコーダ — + と / を含みURLが壊れる
String standard = Base64.getEncoder().encodeToString(data);
System.out.println(standard);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s/c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// URLセーフエンコーダ — クエリパラメータやファイル名で安全
String urlSafe = Base64.getUrlEncoder().encodeToString(data);
System.out.println(urlSafe);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw==

// URLセーフ・パディングなし — JWTやコンパクトトークン向け
String noPadding = Base64.getUrlEncoder().withoutPadding().encodeToString(data);
System.out.println(noPadding);
// aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw

withoutPadding() バリアントは末尾の = 文字を取り除きます。JWT仕様ではヘッダーとペイロードセグメントにパディングなしのURLセーフBase64を要求しているため、 JWTトークンを手動で構築または操作する際は getUrlEncoder().withoutPadding() が正確な呼び出しです。

注意:withoutPadding()メソッドは新しいエンコーダインスタンスを返します——元のエンコーダは変更されません。両方をstatic finalフィールドに格納してスレッド間で安全に再利用できます。

ファイルとAPIレスポンスのエンコード

JavaでBase64エンコードが実際に必要になる最も一般的な2つのシナリオ: ディスクからバイナリファイルを読み込む場合(証明書、画像、設定バンドル)と、 HTTPレスポンスで受け取ったデータをエンコードする場合です。

ファイルをBase64にエンコードする

Java — ファイルのエンコード
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レスポンスボディのエンコード

Java 11+ — HTTPレスポンスのエンコード
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レスポンスをコードを書かずにBase64に変換したい場合は、 オンラインBase64エンコーダ がテキスト・バイナリ両方の入力に対応しています。

コマンドラインでのBase64エンコード

Javaプロジェクトも、IDEも、ビルドステップも不要で、ターミナルから直接文字列やファイルをエンコードしたい場合があります。 多くのUnixシステムには base64 コマンドが同梱されており、JDKがインストール済みであれば jshell でJavaネイティブなアプローチも使えます。

Bash — コマンドラインBase64エンコード
# 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を直接使った1行記述
java -e 'System.out.println(java.util.Base64.getEncoder().encodeToString(args[0].getBytes()))' "my-secret"
# 注意: java -e はJDK 23+が必要 (JEP 477)

jshellアプローチは、 Javaコードとユニックスツールの出力が一致するか確認したいとき、 またはサービスが送信する内容と受信側が期待する内容の不一致をデバッグするときに特に役立ちます。 シェルエイリアスとして登録しておくと便利です。

注意:macOSではbase64コマンドのデコードに-Dを使います。Linux(GNU coreutils)では-dです。エンコードの動作は両者で同一です。Linuxでは-w 0フラグで出力の改行が無効になります——他のコマンドにパイプする際はこれが便利です。

Apache Commons Codec — 高パフォーマンスな代替

ほとんどのアプリケーションではjava.util.Base64 で十分です。しかし、ログ取り込みパイプラインや高スループットのメッセージブローカーなど、 タイトなループで数百万回のエンコード処理をこなす場合は、Apache Commons Codecのベンチマークを検討する価値があります。 Java 8以前から存在し、若干異なるAPIを持つ実績あるライブラリです。

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セーフエンコード
String urlSafe = Base64.encodeBase64URLSafeString(telemetryPayload);

// Base64として有効かチェック
boolean valid = Base64.isBase64(encoded);
System.out.println(valid);  // true

Apache Commons Codecはストリーミングシナリオ向けに Base64OutputStream および Base64InputStream も提供しており、JDKエンコーダにはないバリデーションメソッドも含まれています。 Commons CodecがすでにApacheプロジェクトを経由して依存関係に含まれている場合は、 そのまま使わない理由はありません。

Guava BaseEncoding

GoogleのGuavaライブラリには BaseEncoding が含まれており、設定可能な行セパレータ、パディング制御、標準・URLセーフ両方のアルファベットに対応した 流暢なAPIを提供します。APIは読みやすいですが、Base64エンコードのためだけにGuava(約3 MB)を追加するのは過剰です。 コレクションやキャッシュユーティリティのためにGuavaがすでにプロジェクトに含まれているなら、 エンコードAPIはおまけとして使えます。

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セーフ
String urlSafe = BaseEncoding.base64Url().encode(webhookPayload);

// パディングなし
String noPad = BaseEncoding.base64Url().omitPadding().encode(webhookPayload);

// 行セパレータあり(PEMスタイル)
String wrapped = BaseEncoding.base64()
    .withSeparator("\n", 64)
    .encode(webhookPayload);

Base64.getMimeEncoder() — MIMEおよびPEMの改行付き出力

MIMEエンコーダはMIME仕様(RFC 2045)に従い、76文字ごとに \r\n 改行を挿入します。PEM証明書、S/MIMEメール添付、一部のレガシーAPIはこのフォーマットを要求します。 標準エンコーダとURLセーフエンコーダは1行で出力します——改行付きBase64を期待するシステムにそれらの出力を渡すと、 無言で失敗したりデータが拒否されたりすることがあります。

Java — MIME Base64エンコード
import java.util.Base64;
import java.nio.charset.StandardCharsets;

// PEM証明書本体をシミュレート
byte[] certData = new byte[256];  // 実際には.derファイルから読み込む
new java.security.SecureRandom().nextBytes(certData);

// デフォルトMIMEエンコーダ — 76文字/行、\r\nセパレータ
String mimeEncoded = Base64.getMimeEncoder().encodeToString(certData);
System.out.println(mimeEncoded);
// QYx2K3p8Xg7JmN1R+wFkLd...  (76文字)
// Ht5Bv9CzAq0PnSjYl8WxUe...  (76文字)
// ...

// カスタムMIMEエンコーダ — 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-----");
警告:JWTトークン、HTTPヘッダー、またはURLパラメータにgetMimeEncoder()を使用しないでください。改行がそれらのコンテキストではデータを壊します。代わりにgetEncoder()または getUrlEncoder()を使用してください。

Base64.getEncoder().wrap()による大きなファイルのストリーミング

Files.readAllBytes() でファイル全体を byte[] に読み込む方法は小さなファイルには有効ですが、50〜100 MBを超えると OutOfMemoryErrorのリスクがあります。 JDKが提供する Base64.getEncoder().wrap(OutputStream)は、書き込みながらその場でデータをエンコードする OutputStream を返します。エンコードされたバイトは入力全体をバッファリングすることなく下流のストリームに流れます。

Java — ストリーミングBase64エンコード
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をクローズすると最終パディングバイトが自動的にフラッシュされる
    }
}

try-with-resourcesブロックがフラッシュとクローズを処理します。注意が必要な点として、 最終的なBase64パディングはラッピングした OutputStream がクローズされたときにのみ書き込まれます。クローズを忘れると(または外側のストリームだけクローズすると)、 エンコード出力の最後の数文字が欠落することがあります。

ネットワークソケットへのストリーミング

wrap() メソッドはあらゆる OutputStream に対応します——ファイル出力、ソケット出力、HTTPレスポンスボディ、 ByteArrayOutputStreamも含まれます。 以下はBase64エンコード済みデータをインメモリバッファに直接書き込む例で、 ユニットテストやHTTPで送信するペイロードの構築に役立ちます。

Java — 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)) {
    // チャンクでデータを書き込む — ストリームからの読み込みをシミュレート
    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=

// ラウンドトリップの確認
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
注意:ストリーミング例のバッファサイズ(8192バイト)は任意ではありません。BufferedInputStreamのデフォルトバッファサイズと一致しており、メモリ使用量とシステムコールオーバーヘッドのバランスが取れた値です。バッファが小さいほどread/writeの呼び出し回数が増え、大きすぎるとスループットの改善なしにメモリを浪費します。

スレッドセーフなエンコーダインスタンスの保存と再利用

ファクトリメソッドが返す Base64.Encoder はイミュータブルかつスレッドセーフです。エンコード処理のたびに Base64.getEncoder() を呼ぶと毎回新しいオブジェクトが作成されます。JVMがこれを最適化する可能性はありますが、 エンコーダを static final フィールドに保存することで意図が明確になり、ホットパスでの不要なアロケーションを避けられます。

Java — 再利用可能なエンコーダインスタンス
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class TokenService {
    // 一度作成してどこでも再利用 — スレッドセーフ
    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);
    }
}

このパターンは複数のコントローラやサービスメソッドにまたがってエンコードを処理するユーティリティクラスを持つ Spring Bootサービスで特に有効です。 withoutPadding() 呼び出しは新しいエンコーダインスタンスを返すため、パディングありとなしの両バリアントを 別々のフィールドとして保存できます。 encodeToString() または encode() の各呼び出しはステートレスです——同期化は不要で、共有された可変状態もありません。

よくあるミス

文字セットを指定せずにgetBytes()を呼び出す

問題: charset引数なしのString.getBytes()はプラットフォームのデフォルトエンコーディングを使用します。Windowsではwindows-1252、多くのLinuxシステムではUTF-8、macOSでは環境によって異なります。同じコードが異なるマシンで異なるBase64出力を生成します。

解決策: 常にStandardCharsets.UTF_8を明示的に渡してください。

Before · Java
After · Java
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes();  // プラットフォームデフォルト — 予測不能
String encoded = Base64.getEncoder().encodeToString(bytes);
String text = "Ключ доступа: prod-east";
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(bytes);
URLパラメータに標準エンコーダを使用する

問題: Base64.getEncoder()は+と/を出力します。URLクエリ文字列に含まれると、+はスペースとして、/はパスセパレータとして解釈され、受信側でデータが無言で壊れます。

解決策: URLに現れる値にはBase64.getUrlEncoder()を使用してください。

Before · Java
After · Java
// URLクエリパラメータ内のトークン — 壊れる
String token = Base64.getEncoder()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
// URLセーフエンコード — + と / が含まれない
String token = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;
誤ったエンコーダバリアントでデコードする

問題: getUrlEncoder()でエンコードしてgetDecoder()でデコードする(またはその逆)と、-と_は標準Base64アルファベットでは無効であり、+と/はURLセーフアルファベットでは無効であるためIllegalArgumentExceptionがスローされます。

解決策: 常に対応するデコーダを使用してください:URLセーフにはgetUrlDecoder()、標準にはgetDecoder()。

Before · Java
After · Java
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// その後...
byte[] decoded = Base64.getDecoder()  // 誤ったデコーダ
    .decode(encoded);
// エンコード済みに - や _ が含まれる場合はIllegalArgumentException
String encoded = Base64.getUrlEncoder()
    .encodeToString(data);
// その後...
byte[] decoded = Base64.getUrlDecoder()  // 対応するデコーダ
    .decode(encoded);
wrap()のOutputStreamをクローズしない

問題: ストリーミングエンコーダは完全な3バイトグループを待ちながら最大2バイトをバッファリングします。ラッピングしたOutputStreamをクローズしないと、最終の1〜4文字のBase64(パディングを含む)が書き込まれません。

解決策: try-with-resourcesを使用するか、出力を読み取る前にラップされたストリームのclose()を明示的に呼び出してください。

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()が最終パディングをフラッシュ
String encoded = baos.toString();  // 完全

Base64エンコードメソッドの比較

メソッド
URLセーフ
ストリーミング
改行
カスタム型
インストール
Base64.getEncoder()
✓ (wrap)
不要 (JDK 8+)
Base64.getUrlEncoder()
✓ (wrap)
不要 (JDK 8+)
Base64.getMimeEncoder()
✓ (wrap)
✓ (76文字)
不要 (JDK 8+)
Apache Commons Codec
Maven依存関係
Guava BaseEncoding
✓ (設定可能)
Maven依存関係
jcmd / CLI base64
✓ (pipe)
N/A
システムインストール

ほとんどのプロジェクトでは java.util.Base64 が正解です。依存関係ゼロ、JDK組み込み、スレッドセーフ、RFC 4648の3バリアントをすべてカバーしています。 Apache Commons Codecはすでにクラスパスに含まれていて、 isBase64() バリデーションメソッドやストリーミング Base64OutputStreamが必要な場合に限り使用してください。 Guavaの BaseEncoding はすでにGuavaに依存しているプロジェクトなら合理的な選択ですが、3 MBの依存関係をBase64のためだけに 追加するのは正当化が難しいです。

3つのシナリオ、3つの選択:Basic AuthやJWTエンコードが必要な標準Webサービス? JDKをそのまま使いましょう。SpringやApache HTTP ClientからすでにCommons Codecを引き込んでいるレガシープロジェクト? 使えばいい——クラスパスにBase64ライブラリを2つ持つ理由はありません。 キャッシュやコレクションにGuavaを使っているプロジェクト? そのクリーンな流暢なAPIのために BaseEncoding を使いましょう。Base64エンコードのためだけにライブラリを追加してはいけません——JDK版は2014年から十分な品質です。

Javaコードを実行せずにエンコード結果をすぐ確認したい場合は、 Base64エンコーダ に貼り付けて、コードの出力と一致するか確認できます。

よくある質問

JavaでStringをBase64エンコードするには?

まずgetBytes(StandardCharsets.UTF_8)を使って文字列をバイト列に変換し、そのバイト配列をBase64.getEncoder().encodeToString()に渡します。必ずUTF-8を明示的に指定してください。引数なしでgetBytes()を呼び出すとプラットフォームのデフォルトエンコーディングが使われ、OSや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()はRFC 4648のセクション5で定義されたURLセーフアルファベットを使用します。+を-に、/を_に置き換えることで、URLやファイル名の中でパーセントエンコードなしに使用できます。標準エンコーダが使う+と/はURLのクエリパラメータやパスセグメントと競合します。

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で同じですか?

はい。java.util.Base64 APIはJava 8で導入されて以来変更されていません。クラス、ネストされたEncoderおよびDecoderクラス、すべてのファクトリメソッド(getEncoder、getUrlEncoder、getMimeEncoder)はJava 8、11、17、21で同一です。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==

JavaでファイルをBase64エンコードするには?

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が非推奨になった理由は?

sun.misc.BASE64EncoderはパブリックAPIの一部ではなかったJDK内部クラスです。sun.miscパッケージに存在し、Oracleは使用を明示的に警告していました。Java 8でjava.util.Base64が公式のサポートされた代替として導入されました。Java 9以降のモジュールシステムでは、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);

JavaでBase64のエンコードとデコードをラウンドトリップするには?

Base64.getEncoder().encodeToString(bytes)でエンコードし、Base64.getDecoder().decode(encodedString)でデコードします。デコードされたバイト配列をnew String(bytes, StandardCharsets.UTF_8)でStringに変換します。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 DecoderBase64文字列を元のテキストまたはバイナリ形式に戻す — エンコードの逆操作です。
  • URL EncoderURLで安全に使用するために文字列をパーセントエンコードする — Base64 URLセーフエンコードとは異なりますが、よく併用されます。
  • JWT DecoderヘッダーとペイロードセグメントがBase64urlエンコードされたJSONであるJWTトークンを検査する — ライブラリなしでデコードできます。
  • JSON FormatterBase64エンコードの前後にJSONペイロードを整形する — API連携のデバッグ時に便利です。
他の言語でも利用可能: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.