C++Builder 2009のTMemIniFileとエンコードの挙動を調べた

C++Builder 2009のTMemIniFileとエンコードの挙動を調べた。

結論から先に言うと、エンコードを指定する場合は「TEncoding::Unicode」を使うこと。
TEncoding::UTF8やEncoding:UTF7を使うと、不可思議な挙動に悩まされる。

エンコードを指定しないC++Builder 2007と同じ書き方。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

ファイルには、ANSIのデフォルトのコードページ(Shift_JIS)で保存される。
したがって、文字化けする。

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> ?好

エンコードにTEncoding.Unicodeを指定する書き方。
リトルエンディアンバイトオーダーのUTF-16で保存される。
ファイルには16進数 FFFE のバイトオーダーマークが付く。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::Unicode));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::Unicode));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> 你好

書き込み、読み込みともに問題なく動作する。

なお、ファイルにバイトオーダーマークが付いているので、エンコードを指定しなくても、自動的に識別してくれる。

std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> 你好

エンコードにTEncoding::UTF8を指定する書き方。
UTF-8形式で保存される。
ファイルには、16進数 EFBBBF のバイトオーダーマークが付く。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::UTF8));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::UTF8));
Memo1->Lines->Add(ini->ReadString(L"日本語", L"こんにちは", "no data")); //=> こんにちは
Memo1->Lines->Add(ini->ReadString(L"中国語", L"こんにちは", "no data")); //=> 你好 / ?好

ここで、奇妙な動作になる。

ファイルが存在しないとき、つまり新規保存になるときは正しく、UTF-8で保存される。
ところが、すでにファイルが存在するときには、ANSIのデフォルトのコードページ(Shift_JIS)で保存されてしまう。

TEncoding::UTF8ではなくTEncoding::UTF7を使っても、同様の現象が起こる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください