sakura
sakura copied to clipboard
文字コード自動判定(UTF-8をSJISと誤認)
はじめまして。 身近で文字コード判定で、少し変な挙動があったので、報告します。「こんにちわ」を表示するCプログラムで発現しました。(「こんにちは」では発現しません。)
UTF-8 で
ちわ\
というテキストファイルが、自動判定に任せると、SJISの
縺。繧十
になるという話です。
バイト列で見ると、
e3 81 a1 e3 82 8f 5c
となっていて、UTF-8 と SJIS のどちらでも正しく(!)解釈できます。
ソースコードをざっと見てみました。間違ってたらすいません。
charset/CESI.cpp
の CESI::SortMBCInfo() で、nPoints の最大のエンコードを採用するようです。同点の場合には UTF-8 が優先されるはずですが、この場合には運の悪いことが起こっていました。
nPoints の計算方法を比べてみました。
UTF-8 は void CESI::GetEncodingInfo_utf8( const char* pS, const int nLen )
の num_of_utf8_encoded_bytes、SJIS は void CESI::GetEncodingInfo_sjis( const char* pS, const int nLen )
の num_of_sjis_encoded_bytes で、正しくエンコードできたバイト数を数えているようです。
ただし、7bit文字を除外して数えているので、 UTF-8 なら、末尾の \ を除いた6byte, SJIS なら、途中の半角カナを含めて7byteになり、 SJIS が採用されるという流れのようです。
文字コードの自動判定に完璧を求めるのは、そもそも無理な話だとわかっているのですが、ディフォルトのエンコードを UTF-8 にしていても SJIS に判定されるので、何とかならないかと思ったりもします。(ヒストリはクリアされているという前提です。)
判定の最初の段階で、ディフォルトエンコードでエラーなく読み取れれば、他のエンコードを調べるまでもなく、ディフォルトを採用してくれればいいような気もしていますが、ロジックが複雑になるのは好ましくないでしょうから、悩ましいですね。