UTF-8 テキストを Base64 にエンコードする方法
- 入力 · テキスト にテキストを入力するか貼り付けます。文字コード はすでに UTF-8 に設定されています。
- Base64 は 出力 · Base64 に表示されます。ツールの下の 入力 の数値は UTF-8 のバイト数です。ボックスの上のカウンターは JavaScript と同じ方法で文字を数えるので、絵文字は 2 と数えられます。
- URL やトークン用には URLセーフ(- _) と パディングなし(=) にチェックを入れ、メールや PEM 用には 折り返し を選びます。
- 出力をコピーするか、
base64.txtとしてダウンロードします。
結果をテキストに戻すには Base64 を UTF-8 に を使います。
UTF-8 が文字をバイト列に変える仕組み
UTF-8 は 1 つのコードポイントに 1~4 バイトを使います。ASCII は 1 バイトのままなので、英語のテキストは UTF-8 でも ASCII でも同じようにエンコードされます。それ以外はもっと多くのバイトを使います。
| 文字 | コードポイント | UTF-8 のバイト列 | Base64 |
|---|---|---|---|
A | U+0041 | 41 | QQ== |
é | U+00E9 | C3 A9 | w6k= |
€ | U+20AC | E2 82 AC | 4oKs |
日本語 | U+65E5 U+672C U+8A9E | 9 バイト、1 文字 3 バイト | 5pel5pys6Kqe |
😀 | U+1F600 | F0 9F 98 80 | 8J+YgA== |
Base64 はバイト数にさらに 3 分の 1 を加えるので、中国語や日本語の文は、文字数から Base64 の文字数にするとおよそ 4 倍になり、絵文字 1 つだけでも 8 文字になります。長さに上限のあるフィールドでは注意してください。サイズ計算ツール が役立ちます。
絵文字のシーケンスと肌の色
1 つの絵文字に見えても、実際には複数のコードポイントがつながっていることがよくあります。肌の色は独立した修飾子で、家族や職業の絵文字は目に見えないゼロ幅接合子(U+200D)で複数の人物をつないでいます。
| 絵文字 | コードポイント数 | UTF-8 のバイト数 | Base64 |
|---|---|---|---|
| 😀 | 1 | 4 | 8J+YgA== |
| 👍🏽 | 2(サムズアップ + 中間の肌の色) | 8 | 8J+RjfCfj70= |
| 👨👩👧 | 5(3 人 + 接合子 2 つ) | 18 | 8J+RqOKAjfCfkanigI3wn5Gn |
Base64 文字列やそのデコード後のバイト列をこうしたシーケンスの途中で切ると、文字が壊れます。エンコードした UTF-8 を任意のバイト位置で切り詰めないでください。
同じテキストでもバイト列が違う:Unicode 正規化
Unicode では、2 通りの正しい書き方を持つ文字があります。é は単一のコードポイント U+00E9(合成済み、NFC)にも、e の後に U+0301 COMBINING ACUTE ACCENT が続く形(分解済み、NFD)にもなります。表示はまったく同じですが、バイト列は異なります。
| テキスト | 形式 | バイト数 | Base64 |
|---|---|---|---|
é | NFC | C3 A9 | w6k= |
é | NFD | 65 CC 81 | ZcyB |
naïve | NFC | 6 | bmHDr3Zl |
naïve | NFD | 7 | bmFpzIh2ZQ== |
Apple の古い HFS+ ファイルシステムではファイル名が分解済みの形で保存されますが、ほとんどのキーボードは合成済みのテキストを入力します。Base64 の値を比較したり、署名したり、キーとして使ったりする場合は、先に正規化してください。このツールは貼り付けたコードポイントをそのままエンコードし、正規化は行いません。
コードで UTF-8 を Base64 に
JavaScript の TextEncoder は常に UTF-8 を出力します。入力の出どころがまちまちな場合は、先に正規化してください。
const text = "e\u0301".normalize("NFC");
Buffer.from(text, "utf8").toString("base64"); // "w6k=" (Node.js)
new TextEncoder().encode(text); // Uint8Array [195, 169]
ブラウザでは、TextEncoder のバイト列を、対応していれば bytes.toBase64()(Uint8Array.toBase64)に渡すか、JavaScript のページ にある btoa のヘルパーを通します。
import base64, unicodedata
s = unicodedata.normalize("NFC", "nai\u0308ve")
base64.b64encode(s.encode("utf-8")).decode() # 'bmHDr3Zl'
ファイルやストリーム処理については Python での Base64 を参照してください。
よくある質問
UTF-8 の Base64 は普通の Base64 と同じですか?
同じです。Base64 は常にバイト列をエンコードするもので、「UTF-8 を Base64 に」はどのバイト列かを示しているにすぎません。普通の ASCII テキストなら UTF-8 のバイト列は ASCII のバイト列と同じなので、どちらでも出力は変わりません。
見た目が同じ 2 つの文字列で Base64 が違うのはなぜですか?
Unicode では、一部の文字を複数の方法で書けます。1 つのコードポイントの é は w6k= ですが、e と結合用アクセントの組み合わせは ZcyB です。値を一致させる必要があるなら、エンコードの前に NFC に正規化してください。
エンコーダーは UTF-8 のバイトオーダーマークを付けますか?
いいえ。出力はテキストのバイト列からそのまま始まります。受け手がどうしても BOM を求める場合は、Base64 を 77u/ で始める必要があります。これはバイト列 EF BB BF をエンコードしたものです。
絵文字は何バイトですか?
1 つのコードポイントからなる絵文字は UTF-8 で 4 バイトです。肌の色付きや家族の絵文字は複数のコードポイントからなり、👍🏽 は 8 バイト、家族の 👨👩👧 は 18 バイトです。