概要
Base64 エンコードは、メール添付・REST API のトークン受け渡し・画像のインライン埋め込みなど、バイナリデータをテキストとして安全にやり取りする場面で頻繁に使われます。Java 8 以降は java.util.Base64 が標準で用意されており、外部ライブラリなしで3種類のエンコード方式(標準・URL セーフ・MIME)を使い分けることができます。この記事では、文字列の往復変換、URL に含めても壊れない URL セーフ Base64、バイナリデータの変換といった実務で必要になるパターンを整理します。パディングの有無による挙動の違いや、文字コードの指定を忘れたときに起きる問題など、初見で引っかかりやすいポイントも取り上げます。
使いどころ
REST API の認証ヘッダーにユーザー名とパスワードを Base64 エンコードして Basic 認証トークンを組み立てる
アップロードされた画像ファイルを Base64 文字列に変換し、JSON レスポンスにインラインで埋め込む
URL のクエリパラメータに構造化データを渡すため、JSON 文字列を URL セーフ Base64 でエンコードする
コード例
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class Base64EncodingExample {
/** 文字列を Base64 エンコードして返す */
public static String encode(String text) {
var bytes = text.getBytes(StandardCharsets.UTF_8);
return Base64.getEncoder().encodeToString(bytes);
}
/** Base64 文字列をデコードして返す */
public static String decode(String encoded) {
var bytes = Base64.getDecoder().decode(encoded);
return new String(bytes, StandardCharsets.UTF_8);
}
/** URL セーフ Base64 エンコード(パディングなし) */
public static String encodeUrlSafe(String text) {
var bytes = text.getBytes(StandardCharsets.UTF_8);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
/** URL セーフ Base64 デコード */
public static String decodeUrlSafe(String encoded) {
var bytes = Base64.getUrlDecoder().decode(encoded);
return new String(bytes, StandardCharsets.UTF_8);
}
/** バイナリデータの Base64 往復変換 */
public static boolean verifyBinaryRoundTrip(byte[] data) {
var encoded = Base64.getEncoder().encodeToString(data);
var decoded = Base64.getDecoder().decode(encoded);
return Arrays.equals(data, decoded);
}
public static void main(String[] args) {
// 文字列の往復変換
var original = "Hello, java-recipes! 日本語テスト";
var encoded = encode(original);
var decoded = decode(encoded);
System.out.println("元の文字列: " + original);
System.out.println("エンコード: " + encoded);
System.out.println("デコード: " + decoded);
System.out.println("一致: " + original.equals(decoded));
// URL セーフ Base64
var urlSafe = encodeUrlSafe("test/path?key=value&other=123");
System.out.println("URL セーフ: " + urlSafe);
System.out.println("デコード: " + decodeUrlSafe(urlSafe));
// バイナリデータの往復確認
var binary = new byte[]{0x00, 0x01, 0x02, (byte) 0xFF, (byte) 0xFE};
System.out.println("バイナリ往復: " + verifyBinaryRoundTrip(binary));
}
}Version Coverage
API 自体は Java 8 と同じだが、var による型推論と record で結果をまとめて返すコードが書ける。テキストブロックとの組み合わせも自然。
// Java 17: var + record で結果をまとめる
record EncodingResult(String original, String encoded, String decoded) {}
var bytes = text.getBytes(StandardCharsets.UTF_8);
var encoded = Base64.getEncoder().encodeToString(bytes);
var decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
var result = new EncodingResult(text, encoded, decoded);Library Comparison
注意点
getBytes() を文字コード指定なしで呼ぶと OS のデフォルトエンコーディングが使われ、環境によって結果が変わる。必ず StandardCharsets.UTF_8 を指定すること
URL セーフ Base64 の withoutPadding() を使うと末尾の = が省略される。デコード側が標準デコーダーだとパディング不足でエラーになるため、エンコーダーとデコーダーの組み合わせを揃える必要がある
Base64 はエンコーディングであって暗号化ではない。秘密情報を Base64 でエンコードしただけでは保護にならない。機密データには AES 等の暗号化を併用すること
MIME エンコーダーは76文字ごとに改行を挿入する。HTTP ヘッダーや JSON の値に使うと改行が混入して不具合の原因になるため、用途に応じてエンコーダーを選ぶこと
FAQ
元データの約1.33倍になります。3バイトを4文字に変換するため、おおむね33%増加します。MIME エンコーダーは改行文字が追加されるぶん、さらにわずかに大きくなります。
URL セーフ版は + を - に、/ を _ に置き換えます。URL やファイル名に含めても壊れない文字だけで構成されるため、クエリパラメータやパス要素に直接使えます。
IllegalArgumentException がスローされます。外部から受け取った文字列をデコードする場合は try-catch で囲み、不正入力時の振る舞いを明示的に定義しておくと安全です。