文字を0と1にする
貼り付けた文章は、この画面の中だけで処理します。 未公開の原稿でも、そのまま貼れます。
0と1・1バイト8桁
いちばん読みやすい
出たバイト列11100011 10000001 10000010 01000001 11110000 10011111 10100110 10011011
文字ごとに、何バイトになったか
UTF-8 は文字によってバイト数が変わります。バイト列は1バイトずつ空けて出します (上で選んだ区切り方は、全体を1本にするときの見た目だけを変えます)。
| 文字 | バイト数 | Unicode の番号 | 2進のバイト列 |
|---|---|---|---|
| あ | 3 | U+3042 | 11100011 10000001 10000010 |
| A | 1 | U+0041 | 01000001 |
| 🦛 | 4 | U+1F99B | 11110000 10011111 10100110 10011011 |
数え方ごとの合計
- 文字数人が1文字と感じるまとまり(書記素)
- 3
- Unicode の番号の個数組み合わせ絵文字は、中に何個も入っている
- 3
- UTF-16 の長さJavaScript の length と同じ値
- 4
- UTF-8 のバイト数上のバイト列の長さ
- 8
- バイト数ごとの個数Unicode の番号1つずつで数えたもの
- 1バイトの文字 1個、3バイトの文字 1個、4バイトの文字 1個
先頭の文字は、どのビットが「印」で、どのビットが「中身」か
あ(U+3042)を UTF-8 にすると、3バイトになります。1バイト(8桁)の前のほうが「印」、残りが「中身」です。
| 何バイト目 | 印 | 中身 | 読み方 |
|---|---|---|---|
| 1バイト目 | 1110 | 0011 | 3バイトの文字の先頭 |
| 2バイト目 | 10 | 000001 | 文字の続きの印 |
| 3バイト目 | 10 | 000010 | 文字の続きの印 |
中身だけをつなげると 0011000001000010。 これを2進の数として読むと 12,354 ── つまり U+3042 そのものです。UTF-8 の中に、文字の番号がそのまま入っています。印を付けて分けて置いているだけです。
0と1を文章に戻す
スペース・改行・カンマ・読点・中黒のどれで区切ってあっても読みます。 区切りが無いときは、1バイトぶんの桁数で切ります。
戻した文章あA🦛
8個のかたまりを読んで、8バイトになりました。
よくある質問
日本語の1文字は何バイトですか?
UTF-8 では、ひらがな・カタカナ・漢字・全角記号はどれも3バイトです。英数字と半角記号は1バイト、ウムラウトつきの文字やギリシャ文字は2バイト、多くの絵文字とあとから足された漢字(𠮷 など)は4バイトになります。1文字が何バイトになるかは文字ごとに違うので、このページでは1文字ずつ並べて出しています。
絵文字は4バイトではないのですか?
1つの絵文字なら4バイトですが、組み合わせでできている絵文字はもっと大きくなります。たとえば家族の絵文字 👨👩👧👦 は、人の絵文字4つ(4バイト×4)を、つなぎ役の見えない文字3つ(3バイト×3)でつないだもので、合計25バイトです。見た目は1文字なのに25バイトある、ということが起こります。
2進・16進・10進のどれで見ればよいですか?
目的によります。UTF-8 の仕組みを見たいときは2進です。1バイト目の並びが「この文字は何バイトか」を表しているので、0と1で見ないと分かりません。仕様書やデバッガと突き合わせるときは16進が読みやすく、1バイトがちょうど2桁になります。10進はプログラムのバイト配列と見比べるときに使います。
貼り付けた文章はどこかに送られますか?
送られません。このページはブラウザの中だけで動いていて、文章がサーバーに届く経路そのものがありません。バイト列に直す処理も、元に戻す処理も、すべて手元の端末で行われます。未公開の原稿や社内の文書でも、そのまま貼り付けられます。
バイト列を貼ったら「戻せません」と出ました
どこがどう読めないのかを画面に出しています。よくあるのは、途中で切れている(最後の文字のバイトが足りない)、文字コードが UTF-8 と違う、コピーのときに1バイト抜けた、の3つです。このページは読めたぶんだけを出すことをしません。欠けたまま変換できたように見えるほうが危ないためです。
Shift_JIS だとバイト数は変わりますか?
変わります。Shift_JIS では日本語の多くの文字が2バイトなので、同じ文章でも UTF-8 より小さくなります。ただしこのページが扱うのは UTF-8 だけです。UTF-8 は世界中の文字を1つの表で扱えることから、いまのウェブでは事実上の標準になっています。文字コードの取り違えで文字が崩れた場合は、文字化け復元のページを見てください。
文章を UTF-8 のバイト列にして、2進(0と1)・16進・10進で並べます。どの文字が何バイトになったかも1文字ずつ出します。逆に戻すこともできます。
ひらがなも漢字も3バイト、英数字は1バイトです
コンピュータは文字をそのまま持っているわけではなく、文字に振られた番号を、決まった規則でバイトに直して持っています。 いまのウェブでほぼ全部に使われている規則がUTF-8です。
UTF-8 のいちばんの特徴は、文字によってバイト数が変わることです。 英数字と半角記号は1バイト。ウムラウトつきの文字やギリシャ文字は2バイト。ひらがな・カタカナ・漢字は3バイト。 多くの絵文字と、あとから足された漢字は4バイトです。
だから「同じ100文字」でも、英語なら100バイト、日本語なら300バイトになります。 入力欄の上限や、データベースの桁数がバイトで決められているとき、日本語だけ3分の1しか入らないのはこのためです。 バイトが集まってキロバイトやメガバイトになる先の話はデータ量の変換が引き受けています。あちらは量のものさし、 こちらは1文字ぶんの中身を見るページです。
絵文字はさらに増えます。家族の絵文字(👨👩👧👦)は、人の絵文字4つをつなぎ役の見えない文字3つでつないだものなので、 見た目は1文字でも25バイトあります。 上の表に貼り付けると、その内訳がそのまま出ます。
1バイト目を見るだけで、その文字が何バイトか分かります
ここが UTF-8 のいちばん賢いところです。1バイト目の、先頭のビットの並びだけを見れば、その文字が何バイトかが決まります。中身を読む前に長さが分かる、ということです。
| 1バイト目 | バイト数 | Unicode の番号 | どんな文字か |
|---|---|---|---|
| 0xxxxxxx | 1バイト | U+0000〜U+007F | 英数字と記号。ASCII とまったく同じ並びになる |
| 110xxxxx | 2バイト | U+0080〜U+07FF | ウムラウトつきの文字、ギリシャ文字、キリル文字など |
| 1110xxxx | 3バイト | U+0800〜U+FFFF | ひらがな・カタカナ・漢字・全角記号はここに入る |
| 11110xxx | 4バイト | U+10000〜U+10FFFF | 多くの絵文字と、あとから足された漢字 |
| 10xxxxxx | ― | ― | 文字の先頭ではなく「続き」の印。ここから読み始めることはない |
0で始まれば1バイト、110なら2バイト、1110なら3バイト、11110なら4バイト。 そして続きのバイトは必ず10で始まります。 1バイト目に使う形と、続きに使う形が、まったく重なっていません。
この作りのおかげで、データの途中から読み始めても、文字の切れ目が分かります。 10で始まるバイトを前に戻りながら読み飛ばせば、そこが文字の先頭です。 長い文章の途中で表示を始めたり、うしろから探したりできるのは、この性質のためです。
しかも、印を取り除いて残りをつなげると、Unicode の番号がそのまま出てきます。 たとえば「あ」は3バイトで 11100011 10000001 10000010。 印(1110・10・10)を外して 0011 000001 000010 をつなげると 0011000001000010 ── これは U+3042、まさに「あ」の番号です。UTF-8 は番号を暗号のように変えているのではなく、印を付けて分けて置いているだけです。
英語だけの文章なら、UTF-8 は昔のままのバイト列になります
UTF-8 は、U+0000 から U+007F までの文字を、1バイトのまま置きます。 この範囲は英数字と半角記号、つまりASCIIと呼ばれてきた古い文字の並びです。
つまり、英数字だけでできた文章は、ASCII で保存しても UTF-8 で保存しても、1バイトも違いません。これは偶然ではなく、そうなるように設計されています。 新しい規則を作るときに、古いデータと古いプログラムをそのまま使えるようにしたわけです。 UTF-8 がここまで広まった理由のひとつがこれです。
絵文字は、プログラムから見ると1文字ではありません
JavaScript をはじめ多くの言語は、文字列をUTF-16という別の形で持っています。 UTF-16 は、番号の小さい文字を2バイトで持ち、番号の大きい文字は2つの組で持ちます。この組をサロゲートペアと呼びます。
だから絵文字は、プログラムから見ると2文字ぶんに数えられます。カバの絵文字 🦛 は、UTF-8 では4バイト、UTF-16 では2つぶん、人の目には1文字です。3つの数がどれも違います。投稿しようとして「文字数を超えています」と言われるのは、たいていここです。 数え方そのものを比べたいときは文字数カウントのページへどうぞ。あちらはいくつあるかを数えるところまで、 こちらはそのバイトが実際にどう並んでいるかまで見せます。
気をつけたいのは切るときです。「先頭100文字まで」といった切り方を UTF-16 の数で行うと、サロゲートペアの途中で切れて、片割れだけが残ることがあります。 片割れは UTF-8 で書き表せない番号なので、文句も言われずに EF BF BD(U+FFFD・いわゆる「�」)に置き換わります。 入力に無かったバイトが出てきて、しかも画面には何も出ません。 このページは、その片割れを見つけたらその場で知らせます。
読めないバイト列を、黙って捨てません
逆変換のほうが難しい仕事です。バイト列はどんな並びでも作れてしまうのに、 UTF-8 として意味を持つ並びは、そのごく一部だからです。 このページは、読めないときに空欄を返しません。何バイト目の、どのバイトが、なぜ駄目なのかを出します。
たとえば途中で切れている場合。3バイトの文字の1バイト目まで来たのに、 続きが2バイト残っていなければ、そこで「切れています」と言えます。続きのバイトが続きの形をしていない場合も同じで、 2バイト目以降は必ず10で始まるという決まりがあるので、違えばすぐ分かります。
面白いのは、「書けるのに禁止されている並び」があることです。 たとえば A(U+0041)は1バイトで書けますが、 2バイトや3バイトを使って同じ番号を書くこともできてしまいます。 UTF-8 はこれを禁止しています ── 短く書ける文字は、必ず短く書く決まりです。
禁止の理由は安全のためです。RFC 3629(新しいタブで開きます)の安全に関する節は、正しくない並びを「文字として解釈してしまう」実装への攻撃を挙げています。 入力を調べる仕組みが「この記号は入っていない」と判断したのに、 あとから読む側が長い書き方をその記号として読んでしまえば、検査をすり抜けられます。書き方を1通りに決めておけば、この抜け道そのものが無くなります。
UTF-8 の決まりはRFC 3629(STD 63)(新しいタブで開きます)と Unicode 標準によります。1バイト目の形・4バイトまでであること・上限が U+10FFFF であること・サロゲートの番号を書かないことは、いずれも RFC 3629 に書かれています。 このページは符号化に TextEncoder、読めるかどうかの判定に TextDecoder を使っていて、UTF-8 を自前で組んではいません(どこが不正かを説明するためだけに自前の走査を持っていて、 両者の判定が一致することを単体テストで確かめています)。