テレビのアニメはどこから来る? / 第73話

第73話:イトは、読める文字を打ち直さなかった|文字化けはどこで起きる?

ピコルート第73話。正しいはずの「あ」が「縺�」に変わった。イトは文字を打ち直さず、raw bytesを守ったままdecoderだけを選び直す。Unicode、UTF-8、font、文字化けの役割を一件の復旧でほどきます。

文字コードUnicodeUTF-8文字化け10分更新

第72話の読み取り台に現れた一文字を、イトは透明なcardへ移した。

あ

cardの裏では、三つのbyteが順番を保っている。

E3 81 82

そのcardを、見学用plate printerへ差し込んだ。

preview screenが一度暗くなる。

次に現れたのは、さっきの文字ではなかった。

縺�

イトはsource edit keyへ手を伸ばした。

「壊れたなら、ここへ『あ』って打ち直せばいい」

printerの奥には、12枚のblank plateが積まれている。

resume leverを一度引けば、previewと同じ文字を12枚へ刻み、表面をsealする。

刻んだplateは元のblankへ戻せない。

それでも、次の見学班へ渡すためにはqueueを再開する必要がある。

壊れたのは、文字か、読み方か

ユイはsource edit keyへ透明coverをかけた。

打ち直すことを禁止したのではない。

まず、どこで違ったのかを残すためだ。

マコトはprinterのtraceを三段に分けた。

source bytes        E3 81 82
declared encoding   utf-8
active decoder      shift_jis

source cardの三byteは、第72話から一つも変わっていない。

producer cardにはutf-8と書かれている。

ところがprinterは、別のdecoderを挿したまま読んでいた。

イト

文字が壊れたんじゃなくて、同じbyteを別の約束で読んだのかもしれない

ユイ

raw bytes、作った側の宣言、読む側のdecoderを分けて確認できます

マコト

previewだけ直す前に、どの段で意味が変わったかを固定しよう

Picoはsourceにもdecoderにも触れなかった。

printerの横へ、三つのrecovery cardだけを置いた。

三つの直し方

A:previewへ「あ」と打ち直す

目の前の一枚は読める。

けれど元のsource fileと、printerが次に読む12件は直らない。

B:読める文字が出るまで、三byteを書き換える

偶然読める形になるかもしれない。

しかしproducerが送ったE3 81 82を失い、別のdataを作る。

C:raw bytesを保ち、declared encodingとactive decoderを合わせる

sourceをread-onlyのまま固定する。

printerだけをutf-8へ切り替え、まず一枚をtest decode / test printする。

イトはAのtyping panelを伏せた。

Bのbyte editorも閉じた。

「C。読めないからって、先に手紙を書き換えない。読み方を確かめる」

文字、番号、byte、見た目は別の役割

一枚のcardを、四つの層へ分ける。

1. 文字

人が「あ」として区別したい、抽象的な文字がある。

丸いfontでも角ばったfontでも、同じ文字を表せる。

2. Unicode code point

Unicodeでは、この文字に U+3042 というcode pointが割り当てられている。

code pointは、文字のidentityへ結び付く番号だ。

画面に描く線そのものでも、保存済みbyteそのものでもない。

3. UTF-8 byte sequence

UTF-8は、Unicodeのcode pointを1〜4byteのsequenceとして表すencoding formだ。

このfixtureでは、U+3042をUTF-8で表した三byteが次になる。

U+3042 -> E3 81 82

第72話で守った、exact three bytesだ。

4. Font / glyph

decoderがbyte sequenceをcode pointへ戻したあと、fontが画面の形を描く。

fontを替えれば線の太さや丸みは変わる。

それだけでU+3042が別の文字へ変わるわけではない。

Unicodeはfontの名前ではない。

UTF-8も、日本語だけを表示するmodeではない。

役割を一つに混ぜると、どこを直したのか分からなくなる。

イトがdecoderだけを差し替えた

イトはsource cardへlock sealを置いた。

checksum lampはgreenのまま。

三つのbyteには触れない。

printerからshift_jis decoder cardを抜き、producer cardと同じutf-8を自分の手で差し込んだ。

イトが三つのsource byteを透明なlock coverの下へ保ったまま、printerのwrong decoder cardだけを抜いてdeclared UTF-8 decoderへ差し替えている
raw bytesは変えず、作った側の宣言に合わせて読む側のdecoderだけを切り替える。

test decodeを一回だけ走らせる。

raw bytes before    E3 81 82
raw bytes after     E3 81 82
active before       shift_jis
active after        utf-8
decoded code point  U+3042

previewから縺�が消えた。

代わりに、あが一文字だけ現れた。

イトはまだresume leverを引かない。

一枚のtest plateを選び、自分の目でsource cardと見比べた。

code pointはU+3042。

追加byteは0。

削除byteも0。

replacement characterも0。

そこで初めて、イトはqueueを再開した。

test plates          1
queued plates       12
printed あ          12
mojibake              0
source edits          0

12枚目のsurfaceがsealされる。

Picoは、traceの三段をcyan lightで照らしただけだった。

raw sourceを守ると決め、decoder cardを選び、一件testしてからresumeしたのはイトだ。

文字化けを見たとき、最初に変えないもの

このlabの縺�は、E3 81 82をUTF-8ではないdecoderへ渡したclosed fixtureだ。

実際の文字化けには、encoding labelの取り違え、途中で変換されたdata、欠けたbyte、扱えないsequenceなど、別の原因もある。

だから「読めない文字なら、いつもUTF-8へ変えれば直る」とは限らない。

最初の一手は、変換を重ねることではない。

1. raw bytesを退避する
2. producer / fileのdeclared encodingを確認する
3. active decoderと照合する
4. copyで一件だけtestする

読める文字が偶然出たことだけを正解にしない。

元の宣言、byte sequence、期待するcode pointがつながるところまで確認する。

正しい一文字が、三つの包みを待っていた

print queueが空になると、export trayが開いた。

中には、同じあのdataを待つ三つのcontainerがある。

一つはplain text用。

一つは画像用。

一つはpage document用。

見た目は、どれも同じ白い封筒だった。

イトは一番近いcontainerへ入れようとして、手を止めた。

今回は、中のbyteを書き換えずに読み方を直した。

次は、中身を何として保存し、どのappへ渡すかを決めなければならない。

イトは三byteのlock sealを外さず、containerの口だけを見比べた。

「同じdataでも、包み方を間違えたら、開く側は困るよね」

三つのcontainerに、まだ名前は出ていない。

次回、ピコルート第74話。

File formatは、中のdataをどう読ませる?

この物語を、解説で深める

第73話で生まれた疑問を、解説記事で少し深く見ていきます。物語で感じた不思議さを残したまま、言葉と仕組みを順番に整理しましょう。

文字コードとは|文字を番号として扱うための決まりを読む