Java | Java 標準ライブラリ:Base64

Java Java
スポンサーリンク

Base64 を一言でいうと

java.util.Base64 は、

「バイナリデータ(画像・PDF・任意のバイト列)を、テキスト(英数字+記号)だけで安全にやり取りできるように変換するためのクラス」

です。

ネットワークや JSON/XML など「テキスト前提」の世界で、
生のバイナリをそのまま載せられないときに、

バイト列 → Base64 の文字列
Base64 の文字列 → バイト列

の相互変換をしてくれます。

乱暴に言うと、「どんなバイト列も、壊れにくい安全な文字列に変えるための標準ツール」です。


Base64 がそもそも何をしているのか(直感イメージ)

なぜ「バイト列を文字列にする」必要があるのか

ファイル・画像・暗号化されたデータなどは「バイト列」です。
一方で、よく使うフォーマットやプロトコルは「テキスト前提」です。

たとえば、メールの本文、HTTP の一部、JSON や XML に
そのままバイナリを書き込むと、途中で文字コード解釈がおかしくなったり、
制御文字として誤解されたりして壊れます。

そこで、「どんなバイト列でも、ASCII の安全な文字だけで表現し直す」
という発想が出てきます。

それが Base64 です。

ざっくりした仕組みのイメージ

Base64 の内部の数学的な仕組みをざっくりだけ説明すると、

3 バイト(3×8=24 ビット)を 4 つの 6 ビットの塊に分ける
6 ビットは 0〜63 の 64 通りなので、「64 種類の文字」で表せる
A〜Z, a〜z, 0〜9, +, /(や URL 用に一部変えたもの)を使って 64 種類を表す

ということをひたすら繰り返しています。

細かいビット計算を覚える必要はありません。
「バイト列が、英数字中心の安全な文字列に変わる」とだけ理解しておけば十分です。


Java の Base64 クラスの全体像

java.util.Base64 のエンコーダ/デコーダ

Java 8 以降、java.util.Base64 クラスが標準で使えます。

このクラスは「全部 static メソッド」のユーティリティではありません。
まず「エンコーダ」や「デコーダ」を取得し、それを使って encode/decode します。

たとえば、もっとも基本的な(MIME でも URL でもない)Base64 はこんな感じです。

import java.util.Base64;

public class Base64Basic {
    public static void main(String[] args) {
        Base64.Encoder encoder = Base64.getEncoder();
        Base64.Decoder decoder = Base64.getDecoder();

        String original = "Hello, Base64!";
        String encoded = encoder.encodeToString(original.getBytes());
        byte[] decodedBytes = decoder.decode(encoded);
        String decoded = new String(decodedBytes);

        System.out.println("元の文字列     : " + original);
        System.out.println("Base64 文字列 : " + encoded);
        System.out.println("復元した文字列 : " + decoded);
    }
}
Java

この例のポイントは、

文字列を getBytes() でバイト配列にしている
エンコーダで encodeToString して Base64 文字列を得る
デコーダで decode してバイト配列に戻す
それを new String(...) で文字列化する

という流れです。

Base64 の世界では「常にバイト配列」が本質で、
文字列はその周りにくっついているだけ、と思っておいてください。


一番よく使うメソッドとパターンを押さえる

文字列 → Base64 文字列

テキスト(Java 的には String)を Base64 にしたいときの典型パターンです。

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

public class StringToBase64 {
    public static void main(String[] args) {
        String original = "こんにちは Base64";

        Base64.Encoder encoder = Base64.getEncoder();

        byte[] originalBytes = original.getBytes(StandardCharsets.UTF_8);
        String encoded = encoder.encodeToString(originalBytes);

        System.out.println("Base64: " + encoded);
    }
}
Java

ここで大事なのは、getBytes() に必ず文字コード(StandardCharsets.UTF_8 など)を指定することです。

文字列 → バイト列 に変換するときに、
プラットフォームデフォルトの文字コードに依存しないようにするためです。

Base64 文字列 → 元の文字列

逆方向はこうです。

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

public class Base64ToString {
    public static void main(String[] args) {
        String encoded = "44GT44KT44Gr44Gh44GvIEJhc2U2NA=="; // さっきの出力例だとする

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

        System.out.println("復元: " + decoded);
    }
}
Java

ここでも、new String(byte[], charset) で文字コードを明示的に指定しています。

Base64 自体はバイナリを扱う仕組みなので、
「文字列としてどう解釈するか」は常にエンコード/デコード側が意識する必要があります。


バイナリ(画像ファイルなど)を Base64 にする例

ファイル → バイト配列 → Base64

画像や任意のバイナリファイルを Base64 文字列にしたい場合の流れを見てみましょう。

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

public class FileToBase64 {
    public static void main(String[] args) throws Exception {
        Path path = Path.of("image.png");

        byte[] fileBytes = Files.readAllBytes(path);

        Base64.Encoder encoder = Base64.getEncoder();
        String base64 = encoder.encodeToString(fileBytes);

        System.out.println("Base64 文字列(一部): ");
        System.out.println(base64.substring(0, 80) + "...");
    }
}
Java

これで、image.png の中身が Base64 文字列として手に入ります。

この文字列を JSON に埋め込んだり、
HTML の <img src="data:image/png;base64,......"> のように使ったりできます。

Base64 → バイト配列 → ファイル

逆方向も同じ感覚です。

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

public class Base64ToFile {
    public static void main(String[] args) throws Exception {
        String base64 = "....";  // どこかから受け取った Base64 文字列

        Base64.Decoder decoder = Base64.getDecoder();
        byte[] fileBytes = decoder.decode(base64);

        Path out = Path.of("out.png");
        Files.write(out, fileBytes);

        System.out.println("ファイルとして書き出しました: " + out);
    }
}
Java

Base64 にした時点で「どんな形式のバイナリか」は失われていないので、
元が PNG なら PNG、PDF なら PDF として完全に復元できます。


URL・MIME 用の Base64(getUrlEncoder / getMimeEncoder)

URL 用 Base64(getUrlEncoder / getUrlDecoder)

通常の Base64 では、+/= などの文字が使われます。
これらは URL 的には特別な意味がある文字なので、
そのまま URL パラメータなどに使うと問題が出ることがあります。

そこで、「URL でも安全に使える文字だけに制限した Base64」が用意されています。

import java.util.Base64;

public class UrlBase64Example {
    public static void main(String[] args) {
        String original = "id=123&role=admin";

        Base64.Encoder urlEncoder = Base64.getUrlEncoder();
        Base64.Decoder urlDecoder = Base64.getUrlDecoder();

        String encoded = urlEncoder.encodeToString(original.getBytes());
        String decoded = new String(urlDecoder.decode(encoded));

        System.out.println("URL-safe Base64: " + encoded);
        System.out.println("復元: " + decoded);
    }
}
Java

URL-safe な Base64 は、+- に、/_ に置き換え、= の扱いも変えるなどして
URL に載せても影響が少ないように設計されています。

「トークンを URL パラメータに持たせる」「認証コードをクエリに埋める」などをするときは、
普通の getEncoder ではなく getUrlEncoder を使う方が安全です。

MIME 用 Base64(getMimeEncoder)

メール(MIME)などの仕様では、

76 文字ごとに改行を入れる
などのルールが求められることがあります。

そのために、getMimeEncoder / getMimeDecoder も用意されています。

import java.util.Base64;

public class MimeBase64Example {
    public static void main(String[] args) {
        String original = "とても長いテキスト...(略)";

        Base64.Encoder mimeEncoder = Base64.getMimeEncoder();
        String encoded = mimeEncoder.encodeToString(original.getBytes());

        System.out.println(encoded); // 適宜改行が入る
    }
}
Java

メール関連や MIME ヘッダで Base64 が必要になったときに使います。
普通のアプリ開発では、まず getEncoder / getUrlEncoder だけ押さえておけば十分です。


重要なポイント:Base64 は「暗号」ではない

「変換」であって「秘匿」ではない

初心者がよく誤解するポイントとして、

「Base64 にすると、なんか難しい文字列になるから安全そう(=暗号っぽい)」

というものがあります。

これは完全に誤りです。

Base64 は、「どんなバイナリでもテキストで表現するための変換」に過ぎません。
逆変換は簡単にできるので、「隠す」効果はまったくありません。

「パスワードを Base64 にして保存しているから安心」
というコードを見たら、それは危険な設計です。

本当に保護したい場合は、

Base64 する前に、きちんと暗号化(対称鍵・公開鍵など)
あるいはハッシュ(例えば PBKDF2, bcrypt など)

を行う必要があります。

Base64 は「バイナリをテキストにする」ためのツールであり、
暗号化やセキュリティとは別の話、と頭の中で切り分けてください。


エラー時の挙動と注意点

decode 時の不正な文字列

Base64.Decoder#decode に、Base64 として不正な文字列を渡すと
IllegalArgumentException が投げられます。

信頼できない入力(外部から来た文字列)を decode するときは、
try-catch で包んでおいた方が安全です。

try {
    byte[] bytes = decoder.decode(input);
} catch (IllegalArgumentException e) {
    // Base64 文字列が壊れている
}
Java

サイズが大きくなることに注意

Base64 にすると、元のバイナリサイズよりも約 4/3 倍(約 33% 増し)になります。

大きなファイルをそのまま Base64 文字列として JSON に載せる、
などをやると、通信量やメモリ使用量が想像以上に増えることがあります。

小さなトークンや ID などにはとても便利ですが、
巨大なデータを扱うときは、

本当に Base64 が必要なのか(バイナリのまま送れないか)
分割やストリーミングなどが必要ではないか

も頭の片隅に置いておいてください。


まとめ:Base64 を自分の中でこう位置づける

java.util.Base64 を初心者向けにまとめると、

「バイナリデータを、安全な文字列に変換したり、戻したりするための標準クラス」

です。

特に意識してほしいポイントは、

  • 本質は「バイト配列 ↔ Base64 文字列」の相互変換
  • getEncoder / getDecoder(+ URL/MIME 用のバリエーション)を使う
  • 文字列との行き来では、常に文字コード(UTF-8 など)を意識する
  • Base64 は暗号ではなく、ただのエンコード(変換)である

タイトルとURLをコピーしました