情報Ⅰ 最強120講義

文字のデジタル表現と文字コード|なぜ文字化けは起きるのか【情報Ⅰ第31講】

数強塾グループの一流講師陣 一流のライブ授業×最高品質の映像授業×サボれないコーチング

こんにちは、数強塾代表の藤原進之介です。この記事は参考書『藤原進之介の最強120講義』の第31講「文字のデジタル表現と文字コード」のWeb版です。共通テスト「情報Ⅰ」での重要度はA(頻出。得点差がつく)、情報Ⅱでの接続先は(3)情報とデータサイエンスです。

文字コードは「Shift_JISとUTF-8があります」で終わらせてしまいがちな単元です。しかしそこで止めると、共通テストで問われる「なぜ文字化けするのか」に答えられません。この講では文字が「絵」ではなく「番号」で扱われていることから出発し、番号を振る規則とバイトに詰める規則が別物であること、そしてなぜUTF-8が世界標準になったのかまで、実際に動かした出力を見せながら降りていきます。

1. この講の問い

コンピュータは「あ」という文字をどうやって持っているのか。そしてなぜ、ときどきそれが「謨ー」になるのか。

2. 結論

この講の結論

コンピュータは文字を絵として持っていません。番号として持っています。そして「文字に番号を振る規則(符号化文字集合)」と「その番号をバイト列にどう詰めるかの規則(文字符号化方式)」は別の話です。文字化けは、書いたときと読むときで詰め方の規則が食い違ったときに起きます。同じバイト列が、別の文字として解釈されるからです。

3. なぜそうなるのか

3-1. 文字は「絵」ではなく「番号」である

まずここを外すと、この講は最後まで理解できません。

私たちがディスプレイで見ている「あ」は、確かに絵です。しかしコンピュータの中に入っているのはその絵ではありません。入っているのは 12354 という番号だけです。絵のほうは、フォントファイルという「番号 → 形」の対応表が、表示する瞬間に用意しています。

だからフォントを変えれば同じ「あ」でも形が変わるのに、検索も置換もコピーも問題なく動きます。中身が番号だからです。逆に、フォントを持っていない環境では豆腐(□)になります。番号はあるが形が無い、という状態です。

文字=番号。この1点から、以下すべてが導かれます。

学習指導要領(平成30年告示)解説 情報編でも、情報Ⅰ(2)の解説はデジタル化を「標本化・量子化・符号化」の3語で説明しています。画像は「連続量を測って段階に割り当てる」ところから始まりますが、文字にはそもそも連続量がありません。文字は最初から離散的な種類の集まりです。だから標本化も量子化も要らず、符号化だけがある。ここが音・画像と文字の決定的な違いです。

3-2. 「番号を振る」と「バイトに詰める」は別の話

ここが本講のいちばん重要な分岐点であり、教科書がいちばん雑にまとめる場所でもあります。文字コードと呼ばれているものは、実は2つの層に分かれています。

第1層:符号化文字集合(coded character set)

「どの文字を集合に入れるか」と「それぞれに何番を振るか」を決める規則。例:ASCII、JIS X 0208、Unicode。Unicodeで「あ」は U+3042(10進で12354)と決まっています。

第2層:文字符号化方式(character encoding scheme)

第1層で決まった番号を、実際のバイトの並びにどう変換するかを決める規則。例:UTF-8、UTF-16、Shift_JIS、EUC-JP、ISO-2022-JP。

この2層が別物であることの何より強い証拠は、同じ文字集合に対して複数の詰め方が実在することです。日本語のJIS X 0208という1つの文字集合に対して、日本には少なくとも3つの詰め方が並立してきました。

詰め方 出自 「あ」のバイト列
ISO-2022-JP
(いわゆるJISコード)
電子メール向け。7ビットの世界で日本語を通すため、エスケープシーケンスで「ここから日本語」と宣言する 1B 24 42 24 22
1B 28 42
Shift_JIS パソコン向け。既にある半角カナのバイトを避け、空いている場所に漢字を「ずらして」詰め込んだ 82 A0
EUC-JP UNIX向け。上位ビットを立てて日本語を表す A4 A2

文字集合は同じなのに、バイト列が3通りある。そしてこの3つは互いに区別する仕組みを持ちません。だから日本語圏は、世界でもとりわけ文字化けが起きやすい環境になりました。「Shift_JIS」という名前自体が「ずらした(shiftした)」という設計の由来をそのまま名乗っています。

Unicodeの側も同じで、Unicodeという文字集合に対してUTF-8・UTF-16・UTF-32という複数の詰め方があります。「Unicodeで保存する」という言い方は、厳密には情報が足りていません。

3-3. なぜ文字化けが起きるのか

ここまで来れば答えは短いです。バイト列そのものには「どの規則で詰めたか」が書かれていない。

ファイルの中身は0と1の列でしかありません。E6 95 B0 という3バイトを見せられても、それがUTF-8の「数」なのか、Shift_JISの何かなのかは、バイト列だけからは決まりません。読む側は「これはUTF-8のはずだ」と推測して解釈します。その推測が外れると、別の文字が出てくる。これが文字化けです。

私が授業で必ず言うのは、文字化けは「壊れた」のではないということです。バイト列は1ビットも壊れていません。壊れているのは解釈のほうです。だから正しい規則で読み直せば完全に元に戻ります。逆に言えば、化けた状態で保存し直すと今度こそ本当に壊れる(元の番号が失われる)。「文字化けしたファイルを上書き保存してはいけない」という実務上の鉄則は、ここから出てきます。

化け方には2種類あります。1つは別の文字として読めてしまう場合。バイト列が偶然その方式でも有効な並びだったときで、機械はエラーを出しません。これがいちばん厄介です。もう1つはエラーになる、または置換文字(�)になる場合。その方式ではあり得ないバイトの並びだったときです。

そして国自身が、この現象を授業で確かめさせろと書いています。

数値や文字については,文書を作成して保存する際に,文字数や全角・半角の違い,改行やスペースの入力によって,ファイルサイズが変化すること,Web ブラウザの設定を切り替えることで表示が変化したりすることから,シフト JIS など様々な文字体系があることなどを確認する学習活動が考えられる

文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月(情報Ⅰ(2)イ(ア)。該当箇所は解説p.28相当)

「Webブラウザの設定を切り替えることで表示が変化する」——これはまさに文字化けを意図的に起こして見せろということです。

3-4. 国の資料には「シフトJIS」しか書かれていない

この講を書くにあたって実際に調べ、私が驚いたことを書いておきます。

学習指導要領解説 情報編を全文検索しても、「Unicode」「UTF」という語は1か所も出てきません。出てくる文字コードの固有名詞は、上で引用した「シフト JIS」ただ1つです。

情報Ⅰの教員研修用教材はどうか。第2章のテキストに関する記述は、次の2文で全部です。

コンピュータでは,文字の一つ一つに文字コードと呼ばれる固有の番号を割り当てることで,文字を 2 進法のデータとして取り扱っている。英語などで使用されるアルファベットや数字などの文字は種類が少ないので7bit で表現することができるが,日本語などで使用される漢字などの文字は種類が多いので 16bit で表現する。

文部科学省「高等学校情報科『情報Ⅰ』教員研修用教材」第2章 コミュニケーションと情報デザイン(令和2年)

この章にも「JIS」「Unicode」「UTF」の語は1つも出てきません。さらに文部科学省の「授業・研修用コンテンツ」(情報Ⅰは3単元・計16本)にも、文字コードを扱うコンテンツはありません。

一方で、教員研修用教材の第4章(データの活用)には、CSVを開く場面でこう書かれています。

CSV データを開く際に文字コードの影響により,文字化けする場合がある。この場合には,メニューバーで[データ]に切り替え,「外部データの取り込み」の[テキストファイル]のボタンを使って開くことにより,文字コードを指定して開くことができる

同「情報Ⅰ」教員研修用教材 第4章 情報通信ネットワークとデータの活用(令和2年)。図表5は「AED設置場所データを開いた時の文字化けと対処法」

つまり国の設計では、文字コードは「デジタル表現の理論」としてではなく、「データを扱うときに起きるトラブルとその対処」として置かれているのです。共通テストでは問われるのに、一次資料の本文には理論的な記述がほとんど無い。だから受験生は自分で原理まで降りるしかない。この講がその代わりをします。

なお上の「7bit・16bit」という記述は、原理としては正しいのですが現代の実装の話ではありません。7bitはASCII系統の、16bitはJIS X 0208系の2バイト表現の説明です。今あなたが書いている文章はほぼ確実にUTF-8で保存されていて、日本語1文字は3バイト(24ビット)です。ここは分けて理解しておいてください。

3-5. なぜUTF-8が世界標準になったのか

世界中の文字に番号を振り直そう、というのがUnicodeです。しかし番号を振っただけでは足りません。その番号をどうバイトに詰めるかで、勝負が決まりました。

素朴な案は「全部固定長にする」でした。Unicodeの符号位置はU+0000からU+10FFFFまでなので、4バイト固定にすれば全部入ります(これがUTF-32)。実装は最も簡単です。ではなぜ主流にならなかったのか。

英語圏が損をするからです。

英文のテキストファイルを4バイト固定で保存すると、容量がそのまま4倍になります。それまで A を1バイトで書いていた世界中の既存システム——ファイルシステム、通信プロトコル、コンパイラ、設定ファイル——が、全部作り直しになる。1990年代のネットワークとディスクの事情を考えれば、これは通りません。

UTF-8の設計は、この制約に対する解答でした。UTF-8を定めたRFC 3629(F. Yergeau、2003年11月)はこう書いています。

UTF-8 has the characteristic of preserving the full US-ASCII range, providing compatibility with file systems, parsers and other software that rely on US-ASCII values but are transparent to other values.

IETF RFC 3629 “UTF-8, a transformation format of ISO 10646″(2003年11月)

US-ASCIIの範囲を丸ごと保存する。つまり A はUTF-8でも 0x41 の1バイトのまま。英語だけのファイルは、UTF-8として読んでもASCIIとして読んでも1ビットも変わりません。既存の英語圏のシステムを1つも壊さずに、全世界の文字を扱えるようにした。これがUTF-8が勝った理由です。

その代わり、代償は日本語などが伸びることにあります。UTF-8のバイト列の型はこうなっています。

符号位置の範囲 バイト列の型 バイト数
U+0000 – U+007F 0xxxxxxx 1
U+0080 – U+07FF 110xxxxx 10xxxxxx 2
U+0800 – U+FFFF 1110xxxx 10xxxxxx 10xxxxxx 3
U+10000 – U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4

RFC 3629 の記述による。

日本語の大半(ひらがな・カタカナ・常用漢字)はU+0800 – U+FFFFに入るので3バイトになります。Shift_JISなら2バイトで済んでいたものが1.5倍。日本語圏は容量で損をし、英語圏は損をしない。これは技術的な最適解ではなく、既存資産を壊さないための政治的な妥協の産物です。そこまで理解して初めて「なぜUTF-8なのか」に答えられます。

3-6. UTF-8のもう1つの利点:どこからでも文字の切れ目が分かる

先頭バイトのビットの型をもう一度見てください。1バイト文字の先頭は 0xxxxxxx(最上位が0)。2バイト以上の文字の先頭は 110… 1110… 11110…(最上位が1で、1の個数がバイト数)。途中のバイトは必ず 10xxxxxx。

つまり、バイトを1つ見るだけで「これは文字の先頭か、途中か」が判定できます。RFC 3629はこれを利点として明記しています(Character boundaries are easily found from anywhere in an octet stream)。

Shift_JISにはこの性質がありません。あるバイトが2バイト文字の1バイト目なのか2バイト目なのかは、前から順に読んでこないと分からない。だから途中でずれると、そこから先が全部化けます。UTF-8なら次の先頭バイトで自動的に復帰します。

この「区切りが分かるように符号を設計する」という発想は、実は情報Ⅰの別の場所にも出てきます。教員研修用教材のハフマン符号の説明に「文字の区切りが分からない」という問題が出てきて、それを解決する木の作り方が示されています(データ圧縮の講)。可変長の符号を使うなら、区切りが自力で分かる設計にしなければならない。圧縮と文字コードで、まったく同じ原理が働いています。

3-7. サロゲートペアと「1文字なのに2つ」

もう1つ、身近な現象につながる話をしておきます。

Unicodeは最初「16ビットあれば世界中の文字が入る」という想定で作られました。ところが漢字の異体字・歴史的文字・絵文字が増え、65,536個では足りなくなった。そこでU+10000以降(追加面)が作られたのですが、既に16ビット単位で作られていたUTF-16はそのままでは表せません。

そこでサロゲートペアという仕掛けが入りました。U+D800〜U+DBFF(上位)とU+DC00〜U+DFFF(下位)という2つの範囲をペアで使い、16ビットの単位2つで1文字を表す方式です。

結果として、環境によって「文字数」の答えが変わります。JavaScriptやJavaは文字列をUTF-16の単位で数えるので、追加面の文字は1文字なのに長さ2と返します。Python 3は符号位置で数えるので1と返します。SNSの文字数制限で絵文字が2文字分に数えられたり、逆にされなかったりするのはこの差です。「文字数」という言葉が環境によって別のものを指していることを知っているかどうかで、話が通じるかどうかが変わります。

4. 手で確かめる

以下はすべて私の手元(Python 3・Node.js)で実際に実行し、出力を確認したものです。

4-1. 文字と番号を往復する

print(ord('A'), ord('あ'), ord('漢'))
# 65 12354 28450
print(chr(65), chr(12354), chr(28450))
# A あ 漢
print(hex(ord('A')), hex(ord('あ')), hex(ord('漢')))
# 0x41 0x3042 0x6f22

ord() は文字から番号(符号位置)を、chr() は番号から文字を返します。「あ」の実体は 12354 という整数でした。ここが3-1で述べた「文字=番号」の実物です。16進で書けば 0x3042、Unicodeの書き方で U+3042。16進で書く理由は2進数・10進数・16進数の変換の講のとおりです。

4-2. 同じ文字が、方式によって別のバイト列になる

s = 'あ'
for enc in ['utf-8', 'shift_jis', 'euc_jp', 'iso2022_jp', 'utf-16-be']:
    print(enc, s.encode(enc).hex(' '))
# utf-8      e3 81 82
# shift_jis  82 a0
# euc_jp     a4 a2
# iso2022_jp 1b 24 42 24 22 1b 28 42
# utf-16-be  30 42

同じ「あ」なのに、バイト列が5通りあります。符号位置 U+3042 は1つに決まっているのに、詰め方が違うだけでここまで変わる。3-2で述べた2層の分離が、この出力そのものです。

UTF-16だけ 30 42 で符号位置がそのまま出ていることにも注目してください。16ビットの符号位置をそのまま16ビットのバイト列にしているのだから当然です。ISO-2022-JPの 1b(ESC)で始まる4バイトは「ここから日本語に切り替える」という宣言で、末尾の 1b 28 42 が「英数字に戻す」宣言です。

一方、英数字はこうなります。

print('A'.encode('utf-8'), 'A'.encode('shift_jis'), 'A'.encode('euc_jp'))
# b'A' b'A' b'A'

3方式とも同じ 0x41 の1バイト。これが3-5の「ASCII互換」の実物です。だから英数字だけのファイルは、どの方式で読んでも化けません。文字化けが日本語でしか起きないように見えるのは、このためです。

4-3. UTF-8のバイト列を自分で組み立てる

「あ」= U+3042 を、RFC 3629の型に手で当てはめてみます。U+3042 は U+0800 – U+FFFF の範囲なので3バイト、型は 1110xxxx 10xxxxxx 10xxxxxx。この x に、符号位置の16ビットを上から順に4桁・6桁・6桁と流し込みます。

c = 'あ'
bits = format(ord(c), '016b')
print('符号位置 U+%04X = %s' % (ord(c), bits))
# 符号位置 U+3042 = 0011000001000010
b1 = '1110' + bits[0:4]
b2 = '10'   + bits[4:10]
b3 = '10'   + bits[10:16]
print('組み立て:', b1, b2, b3)
# 組み立て: 11100011 10000001 10000010
print('16進    :', format(int(b1,2),'02X'), format(int(b2,2),'02X'), format(int(b3,2),'02X'))
# 16進    : E3 81 82
print('実際    :', c.encode('utf-8').hex(' ').upper())
# 実際    : E3 81 82

手で組み立てた E3 81 82 と、Pythonが返す E3 81 82 が一致しました。UTF-8は魔法ではありません。番号のビットを、決まった型に流し込んでいるだけです。

4-4. 文字化けを意図的に起こす

s = '数強塾'
b = s.encode('utf-8')
print('UTF-8バイト列:', b.hex(' '), '/', len(b), 'バイト')
# UTF-8バイト列: e6 95 b0 e5 bc b7 e5 a1 be / 9 バイト
print('Shift_JISとして解釈:', b.decode('shift_jis'))
# Shift_JISとして解釈: 謨ー蠑キ蝪セ
print(b.decode('euc_jp'))
# UnicodeDecodeError: 'euc_jp' codec can't decode byte 0xe6
#   in position 0: illegal multibyte sequence

同じ9バイトが、規則を変えるだけで「数強塾」にも「謨ー蠑キ蝪セ」にもなりました。バイト列は1ビットも変えていません。これが3-3で述べた「壊れたのではなく、解釈が違う」です。

そしてEUC-JPとして読もうとするとエラーになります。同じバイト列でも、方式によっては「そもそもあり得ない並び」になるからです。化けるかエラーになるかは、相手の方式次第で決まります。

逆向きもやってみます。

sj = '数強塾'.encode('shift_jis')
print(sj.hex(' '), '/', len(sj), 'バイト')
# 90 94 8b ad 8f 6d / 6 バイト
print(sj.decode('utf-8', errors='replace'))
# 置換文字が5個 + m

Shift_JISなら6バイト、UTF-8なら9バイト。同じ3文字なのにファイルサイズが1.5倍違います。そしてUTF-8として読むと、ほとんどが置換文字(�)になりました。最後の 6d だけが m として生き残っているのは、それがASCII範囲のバイトだからです。

4-5. 文字数とバイト数は別物である

t = 'Joho1 情報'
print('文字数 len():', len(t))
# 文字数 len(): 8
print('UTF-8バイト数:', len(t.encode('utf-8')))
# UTF-8バイト数: 12
print('Shift_JISバイト数:', len(t.encode('shift_jis')))
# Shift_JISバイト数: 10
print('UTF-16バイト数:', len(t.encode('utf-16-be')))
# UTF-16バイト数: 16
print(t.encode('utf-8').hex(' '))
# 4a 6f 68 6f 31 20 e6 83 85 e5 a0 b1

Joho1 と半角スペースで6文字が6バイト、情報の2文字が6バイト。合計8文字12バイト。16進の並びを見れば、前半は1バイトずつ、後半は3バイトずつ区切れるのが目で分かります(e6 83 85 が「情」、e5 a0 b1 が「報」)。

もう少し大きくしてみます。

s = 'Information' * 5 + 'あ' * 100   # 英数字55文字 + 日本語100文字 = 155文字
print(len(s), len(s.encode('utf-8')), len(s.encode('shift_jis')), len(s.encode('utf-16-be')))
# 155 355 255 310

UTF-8は 55 × 1 + 100 × 3 = 355バイト。Shift_JISは 55 × 1 + 100 × 2 = 255バイト。UTF-16は 155 × 2 = 310バイト。すべて手計算と一致します。

この「1文字あたりのバイト数 × 文字数」という形は、画像の講の「1画素あたりのビット数 × 画素数」、音の講の「量子化ビット数 × 標本化周波数 × 秒数」とまったく同じ構造です。情報Ⅰのデータ量計算は、対象が文字か画素か標本かの違いだけで、式の骨格は1つしかありません。

4-6. サロゲートペアを見る

JIS第3水準の漢字「𠮟」(しかる。U+20B9F)で試します。

e = '𠮟'
print('符号位置:', hex(ord(e)))
# 符号位置: 0x20b9f
print('Pythonのlen():', len(e))
# Pythonのlen(): 1
print('UTF-8:', len(e.encode('utf-8')), 'バイト', e.encode('utf-8').hex(' '))
# UTF-8: 4 バイト f0 a0 ae 9f
print('UTF-16の符号単位数:', len(e.encode('utf-16-be'))//2, e.encode('utf-16-be').hex(' '))
# UTF-16の符号単位数: 2 d8 42 df 9f

U+10000を超えているのでUTF-8では4バイト、UTF-16では2つの符号単位(D842 と DF9F)になりました。この2つが3-7で述べたサロゲートペアです。値も手で検算できます。

0x20B9F - 0x10000 = 0x10B9F
上位 = 0xD800 + (0x10B9F >> 10)    = 0xD800 + 0x42  = 0xD842
下位 = 0xDC00 + (0x10B9F & 0x3FF)  = 0xDC00 + 0x39F = 0xDF9F

出力の d8 42 df 9f と完全に一致しました。同じ文字をNode.js(JavaScript)で数えるとこうなります。

const s = '𠮟';
console.log(s.length, [...s].length, s.codePointAt(0).toString(16));
// 2 1 20b9f

length は2、符号位置で数えると1。同じ1文字が、数え方によって1にも2にもなります。文字数制限のあるサービスで絵文字が思ったより多く数えられるのは、これが理由です。

4-7. 3段階を1枚の図にする

文字は3段階に分かれている ① 見える形 フォントが持つ 「番号 → 形」の表 ② 番号 U+3042 = 10進で 12354 符号化文字集合 (Unicode など)が決める ③ バイト列 E3 81 82 (UTF-8) 82 A0   (Shift_JIS) A4 A2   (EUC-JP) 文字符号化方式が決める = ここが食い違うと文字化け よくある取り違え ・①と②を混ぜる → 「フォントを変えたら文字化けした」という誤解が生まれる ・②と③を混ぜる → 「Unicodeで保存した」という不正確な言い方になる ・表示できない(□)は①の問題/別の文字に化けるのは③の問題

図:文字 → 番号 → バイト列。3段階を分けて持つことが、この講の到達点です。

5. 共通テストではこう出る(重要度A)

文字コードは、単独の大問になることは少ないものの、計算の部品としても、原因を問う問いとしても顔を出します。そして2026年1月実施の本試験では、平均点が大きく下がりました。大学入試センターの自己評価にこうあります。

(本試験)の平均点は 56.59 点,標準偏差 15.72 であった。平均点の 56.59 点は昨年度の 69.26 点から約 12.7 点下がった

大学入試センター「令和8年度本試験『情報Ⅰ』自己評価」(問題評価・分析委員会報告書)

同じ資料は、第1問について「得点率は約4割」とも書いています。第1問は小問集合、つまり基本事項の集まりです。基本の理解が浅いところが、そのまま失点になっている。文字コードはまさにその「浅くなりやすい基本」の代表格です。

5-0. 解答欄が16進数を受け付ける設計になっている

意外に知られていないので先に書いておきます。共通テスト「情報」の問題冊子には、こう書かれています。

この試験では,選択肢から選んで答える問題と,解答欄の数字(0〜9)又は文字(a〜f)から選んで答える問題があります。

大学入試センター「試験問題冊子の注意事項及び解答用紙の様式について(令和8年度大学入学共通テスト)」8 情報

そして解答欄の見本には 0 1 2 3 4 5 6 7 8 9 a b c d e f の16個のマークが横一列に並んでいます。16進数1桁をそのままマークできる設計です。文字コード・色コード・IPアドレスなど、16進で答えるのが自然な題材は、この形で出せます。16進変換を機械化しておく必要があるのは、この解答形式のためでもあります。

5-1. 出題の型

型1:データ量の計算(英数字と日本語の混在)

「英数字m文字と日本語n文字からなる文章を、英数字1バイト・日本語3バイトで表すと何バイトか」という型。式は m × 1 + n × 3。符号化方式を変えると答えが変わるので、問題文が「1文字あたり何バイト」と指定しているかを必ず確認します。画像・音のデータ量計算と式の骨格は同じで、単位数 × 1単位あたりの大きさ、それだけです。

型2:文字化けの原因を問う

「同じファイルが環境Aでは正しく表示され、環境Bでは別の文字に見える。原因として最も適当なものを選べ」という型。正解は「保存したときと読み込むときの文字符号化方式が異なるから」。誤答の選択肢に「ファイルが破損した」「フォントが無い」が並ぶのが定石です。ファイル破損なら正しい環境でも読めませんし、フォントが無いなら豆腐(□)になって別の文字にはなりません。3-3と3-1を分けて理解していれば、この2つは即座に切れます。

型3:文字数とバイト数の区別

「この文字列は何文字か、何バイトか」を続けて問う型。全角・半角の混在、半角スペース、改行が仕込まれます。改行も1文字(環境によっては2文字)としてバイトを消費することを忘れないこと。

型4:他分野の部品として

QRコード、通信量の見積り、圧縮率、データベースの文字型の桁数。ここでは文字コードそのものは問われませんが、バイト数が出せないと解けません。

5-2. 落とし穴

  • 「文字コード」という語が2つの意味で使われる。 文字1つに割り当てられた番号を指すこともあれば、方式の名前(Shift_JISなど)を指すこともあります。文脈で読み分けます。
  • 文字数 ≠ バイト数。 特にUTF-8では日本語が3バイト。「1文字=2バイト」と暗記していると外れます。
  • フォントの話と符号化の話を混ぜない。 表示できない(□)のはフォントの問題、別の文字になるのは符号化の問題です。
  • 全角・半角は「見た目の幅」であって、バイト数の話ではない。 半角カナはShift_JISでは1バイトですが、UTF-8では3バイトです。
  • 文字化けはデータの破損ではない。 正しい方式で読み直せば戻ります。
  • UTF-8は「日本語は必ず3バイト」ではない。 追加面(絵文字や第3・第4水準漢字)は4バイトになります。

5-3. 練習用の自作問題(本記事オリジナル)

問題

(1)ある文章は英数字120文字と日本語240文字からなる。英数字1バイト・日本語3バイトで符号化するとき、全体は何バイトか。
(2)同じ文章を、英数字1バイト・日本語2バイトの方式で符号化すると何バイトか。(1)との差は何バイトか。
(3)「あ」の符号位置はU+3042である。UTF-8の3バイト型 1110xxxx 10xxxxxx 10xxxxxx に当てはめて、3バイトを16進で答えよ。
(4)あるファイルを開いたら日本語がすべて別の漢字の列に見えた。ファイルサイズは元のままである。最も考えられる原因は何か。
(5)UTF-16で、符号位置U+0800の文字とU+3042の文字は、それぞれ何バイトになるか。

解答

(1)120 × 1 + 240 × 3 = 840バイト (2)120 × 1 + 240 × 2 = 600バイト。差は240バイト(日本語1文字あたり1バイト × 240) (3)U+3042 = 0011 0000 0100 0010。4桁・6桁・6桁に分けて 0011 / 000001 / 000010 を型に流し込むと 11100011 10000001 10000010 = E3 81 82 (4)保存時と読み込み時で文字符号化方式が食い違っている(文字化け)。サイズが変わっていないのでデータ自体は失われておらず、正しい方式で開き直せば復元できる (5)どちらもU+FFFF以下なので2バイト(UTF-16は基本多言語面を16ビット固定で表し、追加面のみ4バイトになる)

6. 情報Ⅱではこうなる

6-1. まず、テキストマイニングは情報Ⅰの内容である

ここは誤解されやすいので最初に確認しておきます。テキストマイニングは情報Ⅱの話ではありません。情報Ⅰ(4)ア(ウ)にすでに入っています。

データの分析としては,基礎的な分析及び可視化の方法,多量のテキストから有用な情報を取り出すテキストマイニングの基礎やその方法を理解するようにする

前掲「解説 情報編」情報Ⅰ(4)ア(ウ)

学習活動の例まで具体的に書かれています。

新聞記事や小説などをテキストデータとして読み込み,適当な整形等を行った上で,単語の出現頻度について調べさせ,出現頻度に応じた文字の大きさで単語を一覧表示したタグクラウドを作らせ,単語の重要度や他の単語との関係性を捉える学習活動などが考えられる。英語と日本語では,テキストマイニングをする際にどのような部分に違いがあるのかについて討論したり,実際にテキストマイニングを行って比較したりする活動なども考えられる

同上

最後の一文が、この講と直結しています。英語と日本語では何が違うのか。英語は単語と単語の間に空白があります(分かち書き)。日本語にはありません。だから英語は「空白で切る」だけで単語に分けられますが、日本語はどこが単語の切れ目かを機械が判定しなければならない。これが形態素解析です。

情報Ⅰの教員研修用教材 第4章の発展にも、そのまま書かれています。

日本語のテキストマイニングを行うためには,文章を意味のある最小限の単位に分解する形態素解析をしなければならず,そのためのソフトウェアが必要である。有名なものとしては,「MeCab(めかぶ)」と「茶筅(ちゃせん)」の2種類がある

文部科学省「高等学校情報科『情報Ⅰ』教員研修用教材」第4章(令和2年)

同教材はR+RMeCabで「隣の客はよく柿食う客だ」を形態素解析させ、名詞・助詞・名詞・助詞・形容詞・名詞・動詞・名詞・助動詞という出力を示しています。題材は青空文庫の芥川龍之介「杜子春」、成果物はワードクラウドです。

ここで文字コードの話に戻ってください。バイトの切れ目(UTF-8なら3バイトごと)と、単語の切れ目は別物です。「隣の客は」は12バイトですが4形態素です。コンピュータにとって、バイト列を文字に区切るのは規則で決まる機械的作業ですが、文字列を単語に区切るのは辞書と統計を使った推定になります。この2つの「区切り」の性質の違いが、日本語のテキスト分析の難しさの正体です。

6-2. 情報Ⅱでは、単語が「ベクトル」になる

情報Ⅱの教員研修用教材、第3章後半の学習18「テキストマイニングと画像認識」を見ると、同じ青空文庫を題材にしながら、段が1つ上がっています。

「情報Ⅰ」の教員研修用教材と同様に,青空文庫の作品を題材にテキストマイニングの演習を行う。ここでは,Word2vecを用いて,単語の類似度を探る。また,感情分析に関しても少し触れていく。Word2vecとは,テキスト処理のためのニューラルネットワークの応用技術である。テキストを入力することにより,その類似度を学習し,ベクトルとして返す

文部科学省「高等学校情報科『情報Ⅱ』教員研修用教材」第3章 情報とデータサイエンス 後半 学習18(令和2年6月)

研修の目的にも「テキストマイニングに関して、感情分析や類似度などの既存のリソースや技術を用いて分析できる授業ができるようになる」と書かれています。演習の題材は夏目漱石「坊っちゃん」。感情分析では「ポジティブな単語は1に近く、ネガティブな単語は-1に近く設定されている」辞書を用意し、名詞と形容詞を取り出して単語の頻度表にスコアを結合します。

情報Ⅰが「単語を数えて大きさで見せる」(タグクラウド)で終わるのに対し、情報Ⅱは「単語をベクトルにして、類似度と感情を計算する」ところまで行きます。

そしてここが本講の結論につながります。単語をベクトルにできるのは、そもそもテキストが番号の列だからです。もし文字が「絵」として保存されていたら、機械はそれを数えることも比べることもできません。第31講で学んだ「文字=番号」という一点が、情報Ⅱの自然言語処理の土台をそのまま支えています。

6-3. 前処理としての文字コード

情報Ⅱの教員研修用教材 第3章前半の学習12「大量のデータの収集と整理・整形」では、e-Statからダウンロードしたデータを表計算ソフトで前処理させる演習があり、その手順の中に「CSV UTF-8形式で保存する」が明記されています。

情報Ⅰでは文字コードは「知識」でした。情報Ⅱでは、分析パイプラインの最初の工程で必ず通る手続きになります。文字コードを間違えれば、そこから先の分析は全部無意味になる。データサイエンスの現場で最初にぶつかる壁が文字コードであるのは、高校の教材の段階から既にそうなっているのです。

6-4. 情報Ⅰと情報Ⅱの扱いの違い

情報Ⅰ 情報Ⅱ
文字コード 文字に番号を割り当てる仕組み。データ量の計算材料 分析の前処理。読み込み時の指定を誤ると分析全体が壊れる
文字化け 起きる理由を説明できればよい 起きたら直す。データクリーニングの一部
テキスト 人が読む対象 分析対象のデータ(非構造化データ)
単語 出現頻度を数え、タグクラウドで可視化する ベクトルにして類似度・感情スコアを計算する(Word2vec)
形態素解析 「日本語には必要である」と知る(発展扱い) MeCabを実際に動かして分析の入口にする
目的 「どう表しているか」を理解する 「その表現からどんな知識を取り出すか」を作る

情報Ⅰが「表現」で終わり、情報Ⅱは「表現を入力として意思決定する」ところまで行く。基数について書いたのと同じ構図が、文字でもそのまま繰り返されます。

6-5. その先(資格試験)

文字コードは高校で終わる話でもありません。IPAの基本情報技術者試験シラバス Ver.9.2には、大分類1「基礎理論」に独立した項目があります。

(3)文字の表現 代表的な文字コードを理解する。また,10 進数データを表現するためのコードであるゾーン 10 進数などを理解する。
用語例 ASCII コード,EUC(Extended UNIX Code:拡張 UNIX コード),JIS コード,シフト JIS コード,Unicode,UCS

情報処理推進機構「基本情報技術者試験(レベル2)シラバス Ver.9.2」

学習指導要領解説には「シフト JIS」しか出てこなかった固有名詞が、ここでは6つ並んでいます。高校の一次資料に無いからといって「出ない」わけではありません。その先で必ず要求される知識であり、共通テストもその方向を向いています。

まとめ

  • 文字は「絵」ではなく「番号」で扱われている。形はフォントが後から用意する。
  • 文字コードは2層に分かれる。番号を決める符号化文字集合と、番号をバイト列に詰める文字符号化方式は別物。
  • 文字化けは、書いたときと読むときで詰め方の規則が食い違うと起きる。データは壊れておらず、正しい方式で読み直せば戻る。
  • UTF-8が世界標準になったのはASCII互換だから。英数字は1バイトのまま、日本語は3バイトに伸びる。既存の英語圏の資産を壊さないための設計上の妥協である。
  • UTF-8は先頭バイトを見るだけで文字の切れ目が分かる。可変長符号の「区切りの設計」という点で、圧縮のハフマン符号と同じ原理が働いている。
  • サロゲートペアのため、環境によって「文字数」の答えが変わる。JavaScriptでは1文字が長さ2になる。
  • 情報Ⅱでは、単語がベクトルになる(Word2vec)。テキストが番号の列だからこそ機械が数え、比べられる。

出典(すべて2026年8月3日に取得)

  • 文部科学省「高等学校学習指導要領(平成30年告示)解説 情報編」平成30年7月
  • 文部科学省「高等学校情報科『情報Ⅰ』教員研修用教材」第2章 コミュニケーションと情報デザイン/第4章 情報通信ネットワークとデータの活用(令和2年)
  • 文部科学省「高等学校情報科『情報Ⅱ』教員研修用教材」第3章 情報とデータサイエンス 前半・後半(令和2年6月・7月)
  • 文部科学省「高等学校情報科 授業・研修用コンテンツ」
  • 大学入試センター「試験問題冊子の注意事項及び解答用紙の様式について(令和8年度大学入学共通テスト)」
  • 大学入試センター「令和8年度本試験『情報Ⅰ』自己評価」(問題評価・分析委員会報告書)
  • IETF RFC 3629 “UTF-8, a transformation format of ISO 10646″(F. Yergeau、2003年11月)
  • 情報処理推進機構(IPA)「基本情報技術者試験(レベル2)シラバス Ver.9.2」

なお、当塾では共通テストの問題文・選択肢・図表・プログラムは転載していません。本記事で扱っているのは設問構造の説明と、私が作成した類題だけです。本講の位置づけは『藤原進之介の最強120講義』の全体目次から確認できます。デジタル化そのものの考え方はデジタルとアナログの講にまとめました。

執筆:藤原進之介(数強塾グループ代表)

オンライン数学専門塾「数強塾」代表。累計3,500名以上の中高一貫校生を指導。東進ハイスクール・東進衛星予備校・代々木ゼミナールなど出講実績あり。情報Ⅰの参考書を複数執筆しており、KADOKAWA『ゼロから始める情報I』、Gakken『きめる!共通テスト 情報Ⅰ』などがあります。本記事は参考書『藤原進之介の最強120講義』第31講のWeb版です。

藤原進之介のプロフィールを見る

「情報Ⅰ、独学でいけるのか不安」という方へ

数強塾では数学と情報Ⅰの両方に対応したオンライン個別指導を行っています。学習相談は無料、体験授業は3,000円(税込)でお受けしています。

体験授業のご案内つまずき診断(無料・約2分)

情報Ⅰ・情報Ⅱの勉強で詰まっていませんか

この記事を書いているのは、情報Ⅰ専門のオンライン個別指導「情報ラボ」(数強塾グループ)です。講義も過去問も無料で公開しているので、まず全部使ってみてください。

情報Ⅰについて相談する(無料)体験授業(3,000円)

お問い合わせの際は、内容欄に「情報Ⅰ希望」とご記入ください。担当者が直接お返事します。

数強塾オンラインのご案内

体験授業に申し込む入塾受け入れ状況(残席)数学つまずき診断(無料)体験授業の事前案内保護者の方へ高1・高2の方へ医学部志望の方へ保護者様からの声料金・指導システム指導事例・合格実績大学受験 合格実績(集計ルール開示)数強塾グループの理念学校別の数学対策数学の勉強法(記事一覧)数強塾プレミアム(映像授業)獣医学部専門コース鉄緑会・SAPIX等との併用サポート過去問解説・数学問題集情報Ⅰ・情報Ⅱ専門「情報ラボ」情報の過去問アーカイブ(無料PDF)解法テクニック事典(公式・裏ワザ)入試数学の定石(解き方の型・全27章)2026年 夏期講習会2026年 冬期講習会代表・藤原進之介について