Java Base64 デコード — getDecoder

·Backend Engineer·レビュー担当Aisha Osei·公開日

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

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

Java での Base64 デコードは、数日おきに必要になる作業です — Kubernetes の環境変数からシークレットを取り出したり、REST API からバイナリペイロードを読み取ったり、デバッグ中に JWT トークンを検査したりするときに使います。Java の組み込みクラス java.util.Base64(JDK 8 以降)は 3 種類のデコーダーを提供しています:標準 Base64 用の getDecoder()、URL セーフ入力用の getUrlDecoder()、メール添付ファイルのような行折り返しデータ用の getMimeDecoder() です。 コードを書かずにすぐ確認したい場合は、 ToolDeck の Base64 デコーダー をブラウザで即座に使えます。このガイドは Java 8 以降を対象とし、3 種類のデコーダーすべて、wrap(InputStream) によるストリーミング、JWT ペイロードの抽出、ファイルおよび API レスポンスのデコード、代替手段としての Apache Commons Codec、そして本番環境で壊れた出力を生む 4 つのよくあるミスを解説します。

  • Base64.getDecoder().decode(s) が標準的な方法です — JDK 8 から java.util.Base64 に組み込まれており、依存関係は不要です。
  • JWT トークンや OAuth ペイロードには getUrlDecoder() を使います — + と / ではなく - と _ のアルファベットを使用しています。
  • getMimeDecoder() は改行と空白を無視するため、メール添付ファイルや PEM 証明書に最適です。
  • decoder.wrap(InputStream) は大きなファイルをすべてメモリに読み込まずにオンザフライでデコードします。
  • 基本デコーダーは厳格です — 末尾の改行、スペース、または誤ったアルファベット文字があると即座に IllegalArgumentException をスローします。

Base64 デコードとは?

Base64 エンコードは、バイナリデータをテキストのみのチャネル(JSON フィールド、HTTP ヘッダー、XML ドキュメント、メール本文)を安全に通過できるよう、64 文字の ASCII 表現に変換します。デコードはこれを逆転させます。4 つの Base64 文字が元の 3 バイトに対応します。末尾の = パディングは、最後のグループを埋めるために追加されたバイト数を示します。Base64 は暗号化ではありません — 誰でも元に戻せます。その目的は秘密の保護ではなく、転送の安全性です。

Java での典型的なデコードシナリオ:Base64 環境変数として注入された設定値の抽出、クラウド API レスポンスからのバイナリファイルコンテンツの取り出し、PEM エンコード証明書の読み取り、デバッグ中の JWT トークンペイロードの検査などがあります。

Before · text
After · text
ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy
db-prod.us-east-1.amazonaws.com:5432

Base64.getDecoder().decode() — 標準のデコード方法

java.util.Base64 クラスは JDK 8 で追加され、かつて広く使われていた sun.misc.BASE64Decoder を置き換えました。外部依存関係は不要です — import java.util.Base64 して Base64.getDecoder().decode() を呼び出すだけです。このメソッドは String または byte[] を受け取り、デコードされたデータの byte[] を返します。

最小限の動作サンプル

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

public class DecodeCredential {
    public static void main(String[] args) {
        // Kubernetes secret value, Base64-encoded
        String encoded = "ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy";

        byte[] decodedBytes = Base64.getDecoder().decode(encoded);
        String connectionString = new String(decodedBytes, StandardCharsets.UTF_8);

        System.out.println(connectionString);
        // db-prod.us-east-1.amazonaws.com:5432
    }
}

String を構築する際は必ず StandardCharsets.UTF_8 を指定してください。 引数なしの new String(bytes) コンストラクターはプラットフォームのデフォルトエンコーディングを使用し、システムによって異なります。デフォルトが Cp1252 の Windows サーバーでは、マルチバイト UTF-8 文字が静かに壊れます。

ラウンドトリップ検証

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

public class RoundTrip {
    public static void main(String[] args) {
        String original = "redis://cache-prod.internal:6379/session-store";

        String encoded = Base64.getEncoder().encodeToString(
            original.getBytes(StandardCharsets.UTF_8)
        );
        System.out.println(encoded);
        // cmVkaXM6Ly9jYWNoZS1wcm9kLmludGVybmFsOjYzNzkvc2Vzc2lvbi1zdG9yZQ==

        byte[] decoded = Base64.getDecoder().decode(encoded);
        String recovered = new String(decoded, StandardCharsets.UTF_8);

        System.out.println(recovered.equals(original)); // true
    }
}

事前確保バッファへのデコード

3 引数の decode(byte[] src, byte[] dst) オーバーロードは、デスティネーションバッファに直接書き込み、書き込んだバイト数を返します。ホットパスでの余分なアロケーションを避けられます:

Java 8+
import java.util.Base64;

public class DecodeToBuffer {
    public static void main(String[] args) {
        byte[] src = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=".getBytes();
        byte[] dst = new byte[1024]; // pre-allocated

        int len = Base64.getDecoder().decode(src, dst);
        String result = new String(dst, 0, len);

        System.out.println(result);
        // {"host":"10.0.1.50","port":8443}
    }
}
注意:decode() は、入力に Base64 アルファベット外の文字(改行やスペースを含む)が含まれている場合、IllegalArgumentException をスローします。 入力に空白が含まれる可能性がある場合は、getMimeDecoder() に切り替えるか、デコード前に encoded.strip() で除去してください。

非標準型とカスタムオブジェクトへの Base64 デコード

decode() から返された生の byte[] は、UUID、シリアライズされた Java オブジェクト、protobuf メッセージ、タイムスタンプなど、より具体的な型に変換する必要があることが多いです。 デコーダー自体は常にバイト列を返します — ドメイン型への変換は呼び出し側の責任です。

Base64 から UUID へ

Java 8+
import java.util.Base64;
import java.nio.ByteBuffer;
import java.util.UUID;

public class DecodeUUID {
    public static UUID fromBase64(String encoded) {
        byte[] bytes = Base64.getUrlDecoder().decode(encoded);
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        return new UUID(bb.getLong(), bb.getLong());
    }

    public static void main(String[] args) {
        // Compact Base64-encoded UUID from an API response
        String encoded = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
        UUID original = UUID.fromString(encoded);

        // Encode to Base64 (compact form — 22 chars vs 36)
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        bb.putLong(original.getMostSignificantBits());
        bb.putLong(original.getLeastSignificantBits());
        String compact = Base64.getUrlEncoder().withoutPadding()
            .encodeToString(bb.array());
        System.out.println(compact); // 9HrBC1jMQ3KlZw4CssPUeQ

        // Decode back
        UUID recovered = fromBase64(compact);
        System.out.println(recovered); // f47ac10b-58cc-4372-a567-0e02b2c3d479
    }
}

Base64 から Jackson で JSON オブジェクトにデシリアライズ

Java 8+
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;

public class DecodeJsonPayload {
    record DeployEvent(String service, String region, Instant deployedAt, int replicas) {}

    public static void main(String[] args) throws Exception {
        // Base64-encoded JSON payload from a message queue
        String encoded = "eyJzZXJ2aWNlIjoicGF5bWVudC1nYXRld2F5Iiwi"
            + "cmVnaW9uIjoiZXUtd2VzdC0xIiwiZGVwbG95ZWRBdCI6"
            + "IjIwMjYtMDMtMTVUMTQ6MzA6MDBaIiwicmVwbGljYXMiOjR9";

        byte[] jsonBytes = Base64.getDecoder().decode(encoded);
        String json = new String(jsonBytes, StandardCharsets.UTF_8);
        System.out.println(json);
        // {"service":"payment-gateway","region":"eu-west-1",
        //  "deployedAt":"2026-03-15T14:30:00Z","replicas":4}

        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules(); // picks up JavaTimeModule
        DeployEvent event = mapper.readValue(jsonBytes, DeployEvent.class);

        System.out.println(event.service());   // payment-gateway
        System.out.println(event.deployedAt()); // 2026-03-15T14:30:00Z
    }
}
警告:信頼できない Base64 データのデシリアライズに ObjectInputStream を使わないでください。Java のデシリアライズ攻撃はよく知られています — エンコードされたコンテンツが外部ソースから来る場合は、ネイティブ Java シリアライゼーションではなく JSON または protobuf としてパースしてください。

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

すべてのメソッドは java.util.Base64 とその内部クラス Base64.Decoder に属しています。Base64 の 3 つのファクトリーメソッドは異なるデコーダーインスタンスを返し、decode()wrap() メソッドは Decoder インスタンスにあります。

メソッド
戻り値
入力型
説明
getDecoder()
Base64.Decoder
標準デコーダー(RFC 4648 §4、+ と / のアルファベット、= パディングあり)
getUrlDecoder()
Base64.Decoder
URL セーフデコーダー(RFC 4648 §5、- と _ のアルファベット、= パディングあり)
getMimeDecoder()
Base64.Decoder
MIME デコーダー — 行区切り文字および Base64 以外の文字を無視する
decode(String src)
byte[]
String
入力文字列を新しいバイト配列にデコードする
decode(byte[] src)
byte[]
byte[]
入力バイト配列を新しいバイト配列にデコードする
decode(byte[] src, byte[] dst)
int
byte[] + byte[]
事前確保した dst バッファにデコードし、書き込みバイト数を返す
wrap(InputStream is)
InputStream
InputStream
Base64 データをオンザフライでデコードするストリームを返す

getMimeDecoder() — 行折り返しと MIME Base64 のデコード

基本デコーダーは Base64 アルファベット以外のものをすべて拒否します — MIME エンコードされたコンテンツが必ず含む \r\n 改行も例外ではありません。 メール添付ファイル、PEM 証明書、一部の古い API レスポンスは Base64 出力を 1 行 76 文字で折り返します。getMimeDecoder() は行区切り文字や Base64 アルファベット以外の文字を静かに無視するため、そのまま使えます。

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

public class MimeDecode {
    public static void main(String[] args) {
        // PEM certificate body — line-wrapped at 76 characters
        String pemBody = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t\r\n"
            + "TUlJQm96Q0NBVWlnQXdJQkFnSUpBSXBhVDJU\r\n"
            + "aVFvZU1BMEdDU3FHU0liM0RRRU==";

        // getDecoder() would throw IllegalArgumentException here
        byte[] decoded = Base64.getMimeDecoder().decode(pemBody);
        System.out.println(new String(decoded, StandardCharsets.UTF_8));
        // -----BEGIN CERTIFICATE-----
        // MIIBozCCAUigAwIBAgIJAIpaT2T...
    }
}
注意:getMimeDecoder() は寛容です:例外をスローするのではなく、無効な文字をスキップします。既知の MIME データには問題ありませんが、任意の入力に対する破損を静かに飲み込む可能性があります。厳密な検証が必要な場合は getDecoder() を使用してください。

ファイルと API レスポンスからの Base64 デコード

ディスクから Base64 エンコードされたファイルを読み込む

バイナリファイル(画像、証明書、暗号化された blob)がディスク上に Base64 テキストとして保存されていることがあります。ファイルを読み込み、デコードし、バイナリ出力を書き込みます:

Java 8+
import java.util.Base64;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class DecodeFile {
    public static void main(String[] args) {
        Path inputPath = Path.of("tls-cert.pem.b64");
        Path outputPath = Path.of("tls-cert.pem");

        try {
            String encoded = Files.readString(inputPath).strip();
            byte[] decoded = Base64.getMimeDecoder().decode(encoded);
            Files.write(outputPath, decoded);

            System.out.printf("Decoded %d bytes → %s%n", decoded.length, outputPath);
        } catch (IOException e) {
            System.err.println("File error: " + e.getMessage());
        } catch (IllegalArgumentException e) {
            System.err.println("Invalid Base64: " + e.getMessage());
        }
    }
}

HTTP API レスポンスの Base64 フィールドをデコード

クラウド API(AWS KMS、GitHub Contents、Vault)は JSON 内の文字列として Base64 でバイナリデータを返すことがよくあります。まず JSON をパースし、次に対象フィールドをデコードします:

Java 11+
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DecodeApiResponse {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.example.com/secrets/db-password"))
            .header("Authorization", "Bearer sk-prod-9f8e7d6c")
            .build();

        try {
            HttpResponse<String> response = client.send(
                request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() != 200) {
                System.err.printf("Unexpected status: %d%n", response.statusCode());
                return;
            }

            ObjectMapper mapper = new ObjectMapper();
            JsonNode root = mapper.readTree(response.body());

            // API returns: {"name":"db-password","value":"cG9zdGdyZXM6eGs5...","version":3}
            String encodedValue = root.get("value").asText();
            byte[] decoded = Base64.getDecoder().decode(encodedValue);
            String secret = new String(decoded, StandardCharsets.UTF_8);

            System.out.println("Secret: " + secret);
            // Secret: postgres:xk9mP2qR@db-prod:5432/orders
        } catch (Exception e) {
            System.err.println("Failed to fetch secret: " + e.getMessage());
        }
    }
}
注意:デコード呼び出しは IllegalArgumentException 用に、ネットワークエラーとは別の try-catch でラップしてください。I/O 例外とデコード失敗を混在させるとデバッグが難しくなります — API が不正なデータを返したのか、ネットワークが失敗したのかをすぐに把握できるようにしましょう。

コマンドラインからの Base64 デコード

Java プログラムを作る必要がないこともあります。Linux や macOS のシステムには base64 コマンドがあり、JDK 9 以降では jshell でインタラクティブな Java ワンライナーが使えます。デバッグ中のクイック確認には、クラスをコンパイルするより高速です。

bash
# Decode a Base64 string (Linux / macOS)
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode
# {"host":"10.0.1.50","port":8443}

# Decode and pretty-print with jq
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode | jq .
# {
#   "host": "10.0.1.50",
#   "port": 8443
# }

# Quick decode with jshell (JDK 9+)
echo 'System.out.println(new String(java.util.Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==")))' | jshell -
# server-config

# macOS uses -D instead of --decode
echo "c2VydmVyLWNvbmZpZw==" | base64 -D

エンコードされた文字列をブラウザに直接貼り付けたい場合は、 ToolDeck の Base64 デコーダー が標準と URL セーフの両方のバリアントをセットアップなしで処理できます。

高性能な代替手段:Apache Commons Codec

Java の組み込み java.util.Base64 はすでに十分に最適化されています — JDK 11 以降は x86 上でエンコードとデコードにインストリンシクスを使用します。ほとんどのアプリケーションでサードパーティライブラリに頼る理由はありません。とはいえ、Apache Commons Codec はレガシーコードベースで広く使われており、自動的な空白処理によるストリーミングデコード用の Base64InputStream を提供しています。

XML (Maven)
<!-- pom.xml -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.17.0</version>
</dependency>
Java 8+
import org.apache.commons.codec.binary.Base64;

public class CommonsCodecDecode {
    public static void main(String[] args) {
        // Commons Codec is more lenient — handles whitespace and line breaks
        String encoded = "eyJob3N0IjoiMTAuMC4xLjUw\nIiwicG9ydCI6ODQ0M30=";
        byte[] decoded = Base64.decodeBase64(encoded);

        System.out.println(new String(decoded));
        // {"host":"10.0.1.50","port":8443}
    }
}

組み込み API に対する Commons Codec の主な利点は、デフォルトで空白に対して寛容なことと、Java の decoder.wrap() より以前に存在していた Base64InputStream クラスです。Java 8 以降であれば、組み込み API が Commons Codec のすべてをカバーしています。Commons Codec に頼るのは、プロジェクトがすでにそれに依存している場合だけです。

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

200 MB の Base64 ファイルを Files.readString() で読み込んで decode() を呼び出すと、エンコードされた文字列とデコードされたバイト配列で約 350 MB のヒープが確保されます。decoder.wrap(InputStream) はオンザフライでデコードするため、メモリ使用量を一定に保ちます。

Java 8+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

public class StreamDecode {
    public static void main(String[] args) throws IOException {
        Path src = Path.of("database-dump.sql.b64");
        Path dst = Path.of("database-dump.sql");

        try (InputStream in = Base64.getMimeDecoder().wrap(
                 new BufferedInputStream(Files.newInputStream(src)));
             OutputStream out = new BufferedOutputStream(Files.newOutputStream(dst))) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            long total = 0;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
                total += bytesRead;
            }
            System.out.printf("Decoded %d bytes → %s%n", total, dst);
        }
    }
}

Java 9 以降では、read ループを in.transferTo(out) で置き換えられます — 同じことをより少ないコードで実現できます。ファイルに改行が含まれる可能性がある場合(PEM ファイル、メールエクスポート)は、getDecoder().wrap() の代わりに getMimeDecoder().wrap() を使ってください。

Java 9+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

public class StreamDecodeSimple {
    public static void main(String[] args) throws IOException {
        try (InputStream in = Base64.getMimeDecoder().wrap(
                 new BufferedInputStream(Files.newInputStream(Path.of("backup.tar.b64"))));
             OutputStream out = Files.newOutputStream(Path.of("backup.tar"))) {
            in.transferTo(out); // Java 9+
        }
    }
}
警告:getDecoder().wrap() はストリーム内の改行を許容しません。 Base64 データに改行がある(76 文字で折り返されている)場合は、代わりに getMimeDecoder().wrap() を使ってください — そうしないと、ストリームが予測不能な読み取り位置で壊れた出力を生成するか例外をスローします。

JWT ライブラリなしで Java の JWT ペイロードを Base64 デコード

JWT はドットで結合された 3 つの Base64url エンコードされたセグメントで構成されています。中間のセグメントがペイロードです — デバッグ時に確認したい部分です。jjwt や Nimbus を依存関係に追加しなくてもデコードできます。. で分割し、2 番目の部分を getUrlDecoder() でデコードして、結果の JSON をパースします:

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

public class JWTInspect {
    public static String decodeJwtPayload(String token) {
        String[] parts = token.split("\\.");
        if (parts.length != 3) {
            throw new IllegalArgumentException(
                "Invalid JWT: expected 3 segments, got " + parts.length);
        }
        // JWT uses URL-safe Base64 without padding
        byte[] payload = Base64.getUrlDecoder().decode(parts[1]);
        return new String(payload, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {
        String token = "eyJhbGciOiJSUzI1NiJ9"
            + ".eyJzdWIiOiJ1c3ItNjcyIiwiaXNzIjoiYXV0aC5leGFtcGxlLmNvbSIs"
            + "ImV4cCI6MTc0MTk1NjgwMCwicm9sZXMiOlsiYWRtaW4iLCJiaWxsaW5nIl19"
            + ".SIGNATURE_PLACEHOLDER";

        String payload = decodeJwtPayload(token);
        System.out.println(payload);
        // {"sub":"usr-672","iss":"auth.example.com",
        //  "exp":1741956800,"roles":["admin","billing"]}
    }
}

よくあるミス

コードレビューでこれらのミスをすべて見てきました。最初の 2 つが Java サービスにおける Base64 関連の本番バグの大半を占めています。

URL セーフ入力に getDecoder() を使用する

問題: JWT トークンや OAuth アクセストークンは URL セーフアルファベット(- と _)を使用しています。それらを getDecoder() に渡すと、- が標準 Base64 アルファベットにないため IllegalArgumentException がスローされます。

解決策: データのソースを確認してください:認証システムからのトークンには getUrlDecoder() が必要で、MIME 添付ファイルには getMimeDecoder() が必要です。

Before · Java
After · Java
// JWT header — URL-safe, no padding
String header = "eyJhbGciOiJSUzI1NiJ9";
byte[] decoded = Base64.getDecoder().decode(header);
// IllegalArgumentException: Illegal base64 character 2d
String header = "eyJhbGciOiJSUzI1NiJ9";
byte[] decoded = Base64.getUrlDecoder().decode(header);
System.out.println(new String(decoded));
// {"alg":"RS256"}
String 構築時に文字セットを指定しない

問題: new String(bytes) は JVM のデフォルト文字セットを使用するため、環境によって異なります。Linux CI サーバー(UTF-8)と Windows 本番ホスト(Cp1252)は同じバイト列に対して異なる結果を生成します。

解決策: 2 番目の引数として必ず StandardCharsets.UTF_8 を渡してください。

Before · Java
After · Java
byte[] decoded = Base64.getDecoder().decode(encoded);
String result = new String(decoded);
// platform-dependent — may corrupt multi-byte characters
byte[] decoded = Base64.getDecoder().decode(encoded);
String result = new String(decoded, StandardCharsets.UTF_8);
// consistent across all platforms
末尾に空白がある文字列のデコード

問題: ターミナルからコピーしたり設定ファイルから読み込んだ Base64 文字列には、末尾の改行が含まれることがよくあります。基本デコーダーは Base64 アルファベット以外の文字をすべて拒否します。

解決策: デコード前に入力に .strip() を呼び出すか、空白を無視する getMimeDecoder() に切り替えてください。

Before · Java
After · Java
// Read from environment variable — has a trailing newline
String encoded = System.getenv("DB_PASSWORD_B64"); // "cG9zdGdyZXM=
"
byte[] decoded = Base64.getDecoder().decode(encoded);
// IllegalArgumentException: Illegal base64 character a
String encoded = System.getenv("DB_PASSWORD_B64");
byte[] decoded = Base64.getDecoder().decode(encoded.strip());
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// postgres
バイナリデータを String に変換する

問題: バイナリコンテンツ(画像、protobuf、暗号化された blob)に new String(decoded) を呼び出すと無効な String が生成されます。後でバイト列に戻す際、String コンストラクターが無効な UTF-8 シーケンスを置換するため、データが静かに壊れます。

解決策: パイプライン全体でバイナリデータを byte[] として保持してください。コンテンツがテキストだと分かっている場合のみ String に変換してください。

Before · Java
After · Java
byte[] decoded = Base64.getDecoder().decode(pngBase64);
String imageStr = new String(decoded); // corrupts binary
Files.writeString(Path.of("image.png"), imageStr); // broken file
byte[] decoded = Base64.getDecoder().decode(pngBase64);
// Write bytes directly — no String conversion
Files.write(Path.of("image.png"), decoded);

メソッド比較

組み込みデコーダーはほとんどのユースケースをカバーしています。Apache Commons Codec と Guava は古いコードベースで見かける代替手段です。

メソッド
エンコード方式
空白を無視
ストリーミング
カスタム型
要インストール
Base64.getDecoder()
標準 (+, /)
不要 (JDK 8+)
Base64.getUrlDecoder()
URL セーフ (-, _)
不要 (JDK 8+)
Base64.getMimeDecoder()
MIME(改行あり可)
不要 (JDK 8+)
decoder.wrap(InputStream)
任意のバリアント
デコーダーに依存
不要 (JDK 8+)
Apache Commons Base64InputStream
標準 / URL セーフ
要 (commons-codec)
Apache Commons Base64.decodeBase64()
標準
要 (commons-codec)
Guava BaseEncoding.base64().decode()
標準
要 (guava)

JWT トークンや最新の API ペイロードには getUrlDecoder()。メール添付ファイルや PEM 証明書には getMimeDecoder()。メモリが重要な大きなファイルには decoder.wrap(InputStream)。それ以外はすべて getDecoder()。Apache Commons Codec は依存関係ツリーにすでに含まれている場合のみ使用します。

開発中のクイック検証には、 オンライン Base64 デコーダー の方が、ワンオフのクラスを書くより速いです。

よくある質問

Java で Base64 文字列をデコードするには?

java.util.Base64 をインポートして、Base64.getDecoder().decode(encodedString) を呼び出します。戻り値は byte[] です。読めるテキストにするには new String(bytes, StandardCharsets.UTF_8) でラップしてください。JWT など URL セーフ Base64 の場合は、getDecoder() を getUrlDecoder() に切り替えます。

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

byte[] decoded = Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==");
String result = new String(decoded, StandardCharsets.UTF_8);
System.out.println(result); // server-config

Java の getDecoder() と getMimeDecoder() の違いは?

getDecoder() は厳格で、改行を含む Base64 アルファベット以外の文字をすべて拒否します。getMimeDecoder() は行区切り文字(\r\n)を許容し、Base64 以外の文字を無視するため、データが 76 文字単位で折り返されているメール添付ファイルや PEM 証明書のデコードに適しています。

Java 8+
String wrapped = "c2VydmVyLWNv\r\nbmZpZw==";

// getDecoder() throws IllegalArgumentException
// Base64.getDecoder().decode(wrapped); // FAILS

// getMimeDecoder() handles it
byte[] decoded = Base64.getMimeDecoder().decode(wrapped);
System.out.println(new String(decoded)); // server-config

Java で Base64 URL セーフ文字列をデコードするには?

Base64.getUrlDecoder().decode(encoded) を使用します。URL デコーダーは + と / の代わりに RFC 4648 §5 で定義された - と _ のアルファベットを使用します。JWT トークンは常にこのアルファベットを使用します。パディング文字(=)が省略されている場合(JWT では一般的)でも、Java の URL デコーダーはパディングあり・なしの両方の入力を受け付けます。

Java 8+
import java.util.Base64;

// JWT header — URL-safe, no padding
String jwtHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
byte[] decoded = Base64.getUrlDecoder().decode(jwtHeader);
System.out.println(new String(decoded));
// {"alg":"HS256","typ":"JWT"}

Java で大きな Base64 ファイルをストリームデコードするには?

decoder.wrap(inputStream) を使って FileInputStream をラップします。返される InputStream は読み取りながらオンザフライで Base64 をデコードするため、ファイルサイズに関わらずメモリ使用量は一定に保たれます。スループットを最大化するには、BufferedInputStream を経由するか、Files.copy() に直接パイプします。

Java 8+
import java.util.Base64;
import java.io.*;
import java.nio.file.*;

try (InputStream in = Base64.getDecoder().wrap(
        new BufferedInputStream(new FileInputStream("payload.b64")));
     OutputStream out = new FileOutputStream("payload.bin")) {
    in.transferTo(out);
}

Base64.getDecoder().decode() が IllegalArgumentException をスローするのはなぜ?

基本デコーダーは厳格です。改行、スペース、A-Za-z0-9+/= 以外のすべての文字を拒否します。よくある原因は 3 つあります:入力に末尾の改行がある(strip() で除去する)、入力が - や _ などの URL セーフ文字を使用している(getUrlDecoder() に切り替える)、入力が 76 文字単位で折り返されている(getMimeDecoder() に切り替える)。エラーメッセージが不明な場合は生のバイト列を確認してください。

Java 8+
String raw = "c2VydmVyLWNvbmZpZw==\n"; // trailing newline

// Option 1: trim whitespace
byte[] decoded = Base64.getDecoder().decode(raw.strip());

// Option 2: use MIME decoder which ignores whitespace
byte[] decoded2 = Base64.getMimeDecoder().decode(raw);

Java で java.util.Base64 を使わずに Base64 をデコードできますか?

できますが、Java 8+ では使わない理由がありません。Java 8 以前は、sun.misc.BASE64Decoder(内部 API、Java 9 以降削除)、javax.xml.bind.DatatypeConverter.parseBase64Binary()(Java 11 で削除)、Apache Commons Codec が使われていました。これらはいずれも非推奨か追加の依存関係が必要です。java.util.Base64 を使用してください。高速で JDK に同梱されており、3 つのバリアント(basic、URL セーフ、MIME)をすべてカバーしています。

関連ツール

  • Base64 エンコーダー — テキストまたはバイナリデータをブラウザで Base64 にエンコードします。Java ユニットテストに貼り付けるテストフィクスチャの生成に便利です。
  • JWT デコーダー — 3 つの JWT セグメントすべてを一度に分割してデコードし、フィールドごとのペイロード検査ができます — トークンを読むだけなら Java クラスを書くより速いです。
  • URL デコーダー — URL エンコードされた文字列をパーセントデコードします。API レスポンスが Base64url データとパーセントエンコードされたクエリパラメーターを組み合わせている場合に役立ちます。
  • JSON フォーマッター — Base64 JWT ペイロードや API 設定のデコード後、JSON をここに貼り付けてきれいに整形し、構造を検証できます。
他の言語でも利用可能:JavaScriptPythonGoC#
PN
Pavel NovakBackend Engineer

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.

AO
Aisha Osei技術レビュアー

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.