2010年05月06日
QTextCodec の円記号問題
Qt の QTextCodec で、Shift_JIS から Unicode に変換する際に、いわゆる「円記号問題」にはまってしまったのでメモしておきます。
Qt の QString や QChar は、Unicode 4.0 を、QChar は UTF-16 (サロゲートペアサポート)、QString は UTF-8/UTF-16 のいずれかで持っています。
Qt 4.3 QChar Class Reference
Qt 4.3 QString Class Reference
Qt の QTextCodec::toUnicode() で Shift_JIS から Unicode に変換すると、Shift_JIS の円記号(0x5c) が、U+00a5 に変換されるようです。これにより起こる問題が「円記号問題」です。
ja.wikipedia/円記号/Unicodeにおける問題点(円記号問題)
Windows のファイルパスなどに使用されるメタ文字 '\\' は (ASCII で言うところの) バックスラッシュ (U+005c) であり、円記号 (U+00a5) ではありません。そのため、U+00a5 に変換されてしまうと、ファイルパスの区切りではなく、円記号 (U+00a5) を含む非常に長いファイル名として扱われてしまいます。(今回はまった問題はこれです。ユーザがダイアログで選択したファイルパス (Unicode) を Shift_JIS に変換して設定ファイルにセーブし、それをまたロードした時に円記号問題が起こりました。)
Microsoft の環境では、現実的な解決策として、0x5c は U+005c に変換されるので、普段はあまり意識しないで済むようです。
今回はこの問題を避けるために、Shift_JIS ではなく、UTF-8 のまま QString のファイルへのセーブとロード、外部とのやりとりをすることにしました。
下記のブログ記事では、QString::replace() で U+00a5 を U+005c に変換していますが、問題になるのは円記号だけではなく、チルダなどの他の文字でも起こり得る問題のため、今回はこの方法は使用しませんでした。
http://d.hatena.ne.jp/yaneu/20100223
参考文献:
プログラマのための文字コード技術入門
8.5 円記号問題
Qt 4.3 QChar Class Reference
Qt 4.3 QString Class Reference
Qt の QTextCodec::toUnicode() で Shift_JIS から Unicode に変換すると、Shift_JIS の円記号(0x5c) が、U+00a5 に変換されるようです。これにより起こる問題が「円記号問題」です。
ja.wikipedia/円記号/Unicodeにおける問題点(円記号問題)
Windows のファイルパスなどに使用されるメタ文字 '\\' は (ASCII で言うところの) バックスラッシュ (U+005c) であり、円記号 (U+00a5) ではありません。そのため、U+00a5 に変換されてしまうと、ファイルパスの区切りではなく、円記号 (U+00a5) を含む非常に長いファイル名として扱われてしまいます。(今回はまった問題はこれです。ユーザがダイアログで選択したファイルパス (Unicode) を Shift_JIS に変換して設定ファイルにセーブし、それをまたロードした時に円記号問題が起こりました。)
Microsoft の環境では、現実的な解決策として、0x5c は U+005c に変換されるので、普段はあまり意識しないで済むようです。
今回はこの問題を避けるために、Shift_JIS ではなく、UTF-8 のまま QString のファイルへのセーブとロード、外部とのやりとりをすることにしました。
下記のブログ記事では、QString::replace() で U+00a5 を U+005c に変換していますが、問題になるのは円記号だけではなく、チルダなどの他の文字でも起こり得る問題のため、今回はこの方法は使用しませんでした。
http://d.hatena.ne.jp/yaneu/20100223
参考文献:
プログラマのための文字コード技術入門
8.5 円記号問題