RM-BLOG

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

UTF-8の2バイト文字の存在を失念していたことによる失敗談(+サクラエディタの見え方の違和感)について

バージョンとか設定とかにもよるのかもしれないが、サクラエディタは、中途半端にブチ切れられたUTF-8文字コードを上位サロゲートの一部と見做して文字コード表示してしまうらしい。バイナリエディタとかで中身を見ると実際のコードは違ったりする。

例えば「あ」だが、UTF-8では「E3-81-82」の3バイト。
これを無理やり「E3」「81」「82」の1バイトずつにぶった切って保存すると、
「E3」は「U+DCE3」
「81」は「U+DC81」
「82」は「U+DC82」
で表示される。

実験として「あ」を無理やり1バイトでブチきったときのスクリーンショット
「E3」部分
20170529_neta_01_UTF-8_E3.jpg

上位サロゲートUnicodeでU+DC00~U+DFFFの範囲なので「E3」という1バイトが勝手に上位サロゲート範囲の文字の一部として扱われてしまっている。
UTF-8の1バイト文字のコード範囲は「00」~「7F」までなので、「E3」というバイトは定義外にあたるため、
エディタの都合上無理矢理サロゲート範囲に位置づけているという考えもなくはない。
そもそも「文字」としては表現できないコード値なので、テキストエディタにこれをちゃんとコード値で表現しろというのも酷な話な気がするが
最初は「なんで突然サロゲートなんか出てきてるんだ?おい?」と思って軽くビビった。


 

 
事の発端は「UTF-8の全角文字項目を100桁で切る」というロジックのバグである。
全角文字=1文字3バイトという(今にして思えば思慮の浅い)固定観念に基づき、
「100桁(文字)=300バイトで切ればいい」という考えに基づいてホントに無策に300バイトでブチ切ったら末尾に↑みたいな変なコード値の文字が出力されたのである。
理由は、この全角文字項目に2バイト文字が入ってきたから。
これにより、文字数とバイト数は単純に3倍すれば計算できる比例関係にならない。
例えば「あいうえαお」というUTF-8の文字列を「5桁=15バイトで切る」としたとき、
「α」が2バイト文字である関係で15バイト目は「α」の末尾にならず、「お」を構成する3バイトのうち先頭1バイト目だけが対象になって切り出されてしまう。
実際ブチ切ると以下のようになるであろう。

通算バイト :  1  2  3  4  5  6  7 8   9 10 11 12 13 14 15 16 17
コード     : E3-81-82 E3-81-84 E3-81-86 E3-81-88 CE-B1 E3-81-8a
文字       : あ       い       う       え       α    お
↓
↓
15バイトでブチ切る
↓
↓
通算バイト :  1  2  3  4  5  6  7 8   9 10 11 12 13 14 15
コード     : E3-81-82 E3-81-84 E3-81-86 E3-81-88 CE-B1 E3
文字       : あ       い       う       え       α    (お)

というかんじである。
「E3」というコード値だけが文字の途中で中途半端に切り出されてしまい不正コード値として出力される。

この件が起きるまで、2バイト文字の存在を知っていたものの、「UTF-8の全角文字は3バイト」というある種の固定観念があったのは事実であり、
ほとんど意識してなかった2バイト文字に痛いところを突かれてしまったのは個人的にも反省すべき点であると思っている。
まあそういう意味でも、これはロジックの考慮漏れなんだから、この件でサクラエディタを糾弾(?)するのはお門違いだよね。
っていうかそもそもなんでバイトで切るようにしてるんだか理解出来ん
っていう愚痴が出るのは自分で作ったプログラムじゃないからですね。
意味の責任逃れでした。ハイ。