1

ファイルから Unicode テキスト (UTF-16 LE、改行区切り) の行を読み取りたい。Visual Studio 2012 を使用しており、32 ビットのコンソール アプリケーションをターゲットにしています。

WinAPI 内に ReadLine 関数が見つからなかったため、Google に問い合わせました。そのような機能を求めたのは私が初めてではないことは明らかです。最も一般的に推奨される解決策は、std::wifstream を使用することです。

次のようなコードを書きました。

wchar_t buffer[1024];
std::wifstream input(L"input.txt");

while (input.good())
{
    input::getline(buffer, 1024);
    // ... do stuff...
}

input.close();

説明のために、input.txt には、長さが 200 wchar_t 文字未満の 2 つの UTF-16 LE 行が含まれていると仮定します。

初めて getline を呼び出す前に、Visual Studio はバッファーが wchar_t の配列であることを正しく識別します。デバッガーで変数にマウスを合わせると、配列が 16 ビット値で構成されていることがわかります。ただし、getline への呼び出しが返された後、デバッガーはバッファーをバイト配列であるかのように表示するようになりました。

getline を最初に呼び出した後、buffer の内容は正しいものになります (buffer がバイト配列のように扱われることを除けば)。input.txt の最初の行に UTF-16 文字列 L"123" が含まれている場合、これは (16 進数) "31 00 32 00 33 00" として正しくバッファーに格納されます。

私の最初の考えは、reinterpret_cast<wchar_t *>(buffer)どちらが望ましい結果を生成するか (バッファは wchar_t 配列のように扱われるようになりました) であり、期待する値が含まれています。

ただし、getline への 2 回目の呼び出しの後 (input.txt の 2 行目に文字列 L"456" が含まれています)、バッファーには (16 進数) "00 34 00 35 00 36 00" が含まれます。これは正しくないことに注意してください ([hex] 34 00 35 00 36 00 のはずです)。

バイト順がおかしくなるという事実は、これを回避するための解決策として reinterpret_cast を使用することを妨げています。さらに重要なのは、なぜ std::wifstream::getline が wchar_t バッファーを char バッファーに変換するのですか?? chars を使用したい場合は ifstream を使用し、wchar_t を使用したい場合は wifstream を使用するという印象を受けました...

私は stl ヘッダーを理解するのが苦手ですが、wifstream が意図的に wchar_t を char に変換しているように見えます...なぜ??

これらの問題を理解するための洞察と説明をいただければ幸いです。

4

1 に答える 1

8

wifstreamファイルからバイトを読み取りcodecvt、ストリームのロケールにインストールされたファセットを使用してワイド文字に変換します。デフォルト ファセットは、システムのデフォルト コード ページを想定mbstowcsし、それらのバイトを呼び出します。

ファイルを UTF-16 として扱うには、codecvt_utf16. このように

std::wifstream fin("text.txt", std::ios::binary);
// apply facet
fin.imbue(std::locale(fin.getloc(),
          new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));
于 2013-10-31T04:27:52.687 に答える