ペペロン頭脳

いわゆるエスアイヤーに勤めてるけどまともにエスアイやったことないITエンジニアのメモ的なアレ。

UnicodeプロジェクトでのCStdioFile::WriteStringにハマる

プロジェクトの文字セットにUnicodeを指定したら、CStdioFile::WriteStringでASCII範囲外の文字が書き出せない!
なかなか原因を特定できず、小一時間はまってしまったが、どうやらよく知られた問題の模様。
VisualStudioが標準文字セットをUnicodeにしてから久しいですが、CStdioFileの実装はMBCSを前提にしたまま、というのが原因のようです。
ロケールを指定してやればOKだよ!という解説が各所で展開されております。

[MFC] UnicodeプロジェクトでのWriteString - かえでのWebログ


ところが、これ実際に試してみると日本語指定の場合はShift_JIS、タイ語指定ならISO-8859-11といった具合に、変換された文字セットで書き込みが行われる。
多言語が入り混じる文字列の場合は役に立ちません。
じゃあUnicodeのまま書き出したいときはどうするのか?

ひとまず簡易的に、wchar_tの変数が持つ値(VC++ならUTF-16オクテットと等価)をCFile::Writeで直書きする方針でやってみました。
これしか方法ないんですかね。もしくは一手間加えてマルチバイト文字列に変換してからUTF-8として書き出すか・・
もっとスマートな方法ご存知の方、教えてプリーズ。

// プロジェクトの文字セット設定はUnicode
// typeBinaryでファイル作成
CFile f(_T("C:\hoge.txt"), CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite|CFile::typeBinary);

CString strText = _T("123abcあいうราชอาณาจักรไทย"); // ราชอาณาจักรไทย:タイ王国

f.SeekToEnd();
// サロゲートペア考慮せず
f.Write((PCWSTR)strText, strText.GetLength() * sizeof(TCHAR));
f.Flush();
f.Close();

余談ですが、タイの首都バンコクの正式名称はめちゃくちゃ長い。
(Wikipediaより)

กรุงเทพมหานคร อมรรัตนโกสินทร์ มหินทรายุธยา มหาดิลกภพ นพรัตน์ราชธานีบุรีรมย์ อุดมราชนิเวศน์มหาสถาน อมรพิมานอวตารสถิต สักกะทัตติยวิษณุกรรมประสิทธิ์

イン神(インドラ、帝釈天)がウィッサヌカム神(ヴィシュヌカルマ神)に命じてお作りになった、神が権化としてお住みになる、多くの大宮殿を持ち、九宝のように楽しい王の都、最高・偉大な地、イン神の戦争のない平和な、イン神の不滅の宝石のような、偉大な天使の都。

イン神!イン神!イン神!