文字コードの円記号問題を復習したのでメモ。
円記号問題
参考)
円記号 - Wikipedia
ざっくり
例えばmacのvscodeにて、文字コードをshift-jisに設定して[¥]を入力して保存したあと、一度閉じて再度Shift JIS指定で開くと[¥]で保存したはずなのに[\]が表示されている。
何故こんなことが起こるのかというと、shift-jisでは[¥]と[\]は同一の文字であるから。
文字を表すバイト列は[¥]も[\]も5cになる。
バイト列5cを[¥]として表示するか、[\]として表示するかはフォントやエディタによりけりという感じ。
つまり、shift-jisで[¥]と入力すると、5cというバイト列で保存され、次に読み込みされた際には[\]として表示されたという感じ。
shift-jisとUnicode間での変換を行う際の問題
shift-jisに対して、unicodeでは[¥]と[\]はバイト列が異なる。 utf-8において、[¥]は5cになり、[\]はc2a5になる。
unicodeとshift-jisで1:1で対応していない状況なので変換を行うと問題がおこる。
unicodeで[¥\]と入力した文字列をshift-jisに変換して、再度unicodeに戻すと[\\]になってしまう。
これは、shift-jisに変換した際、[¥]と[\]の区別がないので両方とも[\(5c)]に変換されて区別がなくなってしまう。 その後、再度utf-8に変換する際には[\]に変換され、結果[¥\]は[\\]になってしまう。
フォントによって(主にWindows環境)は[\]は[¥]と表示されている
ややこしいが、[\]は歴史上の問題で主にWindows環境では[¥]と表示されている場合が多い。 Windowsでこの記事を見たら意味わからないことになっていそう。。(ブラウザ用のフォントはいい感じになってたりするのかも?)
バイト列を確認したりいじったりする方法
上記のように[\]と[¥]で見た目がフォントによっては全く同じだったりするので、どちらが出力されているのかはバイト列で確認するのが確実。
以下のテキストのバイト列を確認するには、
\ ¥
以下のようにコマンドを叩く。
od -tx1 sample.txt 0000000 5c 0a c2 a5 0000004
まず[\](5c)が出力されており、次にLF(0a)が出力されて改行され、次に[¥] (a5)が出力されていることがわかる。
バイナリエディタを使えば、直接文字コードを打って表示を確認することもできる。
参考図書(かなり面白かった)