2

更新: @Potatoswatter と @Jonathan Leffler のコメントに感謝します。かなり恥ずかしいことに、wstring の値が正しく表示されないデバッガー ツール ヒントに気付きましたが、それでもうまく機能せず、質問を更新しました。下:

文字列に読み込みたい小さなマルチバイトファイルがある場合、次のトリックを使用します-たとえばgetline、区切り文字で使用します'\0'

std::string contents_utf8;
std::ifstream inf1("utf8.txt");
getline(inf1, contents_utf8, '\0');

これにより、改行を含むファイル全体が読み込まれます。
ただし、ワイド文字ファイルで同じことを実行しようとすると、機能しませんwstring。最初の行までしか読み取れません。

std::wstring contents_wide;
std::wifstream inf2(L"ucs2-be.txt");
getline( inf2, contents_wide, wchar_t(0) ); //doesn't work

たとえば、Unicode ファイルに CRLF で区切られた文字 A と B が含まれている場合、16 進数は次のようになります。

FE FF 00 41 00 0D 00 0A 00 42

マルチバイトファイルで getline with '\0' がファイル全体を読み取るという事実に基づいて、getline( inf2, contents_wide, wchar_t(0) )ユニコードファイル全体を読み取る必要があると信じていました。ただし、そうではありません。上記の例では、ワイド文字列に次の 2 つの wchar_ts が含まれます。FF FF

( wchar_t(0) を削除すると、期待どおりに最初の行に読み込まれます(つまりFE FF 00 41 00 0D 00)

wchar_t(0) が wchar_t の区切りとして機能しないのはなぜ00 00ですか?
ありがとうございました

4

3 に答える 3

2

UCS-2デコーダーが誤動作しています。getline( inf2, contents_wide )onの結果は=にFE FF 00 41 00 0D 00 0A 00 42なります。Windowsを使用していると仮定すると、行末は適切に変換され、バイト順マークは出力に表示されないはずです。0041 0000L"A"

ロケールの設定方法に関して、OSのドキュメントを再確認することをお勧めします。

編集:ロケールを設定しましたか?

locale::global( locale( "something if your system supports UCS-2" ) );

また

locale::global( encoding_support::ucs2_bigendian_encoding );

ここで、encoding_supportはライブラリです。

于 2010-04-28T00:11:34.873 に答える
1

次の質問を参照してください: C++ のワイド ファイル ストリームは、デフォルトで書き込まれたデータを狭めるのはなぜですか? wchar_t、書き込み時にポスターが->char変換に驚いているところ。

その質問に対する答えは、読書の場合にも当てはまります。簡単に言えば、最も低いレベルでは、ファイル I/O は常にバイト単位で行われます。A basic_filebuffstream実際にI / Oを実行するために使用するもの)は、codecvtファセットを使用して、「内部」エンコーディング(プログラムによって表示され、ストリームをインスタンス化するために使用されるchar型wchar_t)と「外部」エンコーディングの間で変換しますファイルの (これは常にですchar)。

codecvt、ストリームの から取得されますlocaleimbue()ストリームで -d が指定されたロケールがない場合は、グローバル ロケールが使用されます。デフォルトでは、グローバル ロケールは「クラシック」(または「C」) ロケールです。そのロケールのcodecvtファセットはかなり基本的なものです。標準がそれについて何を言っているのかわかりませんが、Windowsでの私の経験では、との間で1つずつ「キャスト」するだけcharですwchar_t。Linux でもこれを行いますが、文字の値が ASCII 範囲外の場合は失敗します。

したがって、ロケールに触れない場合 (imbue()ストリームで 1 つを使用するか、グローバル ロケールを変更することによって)、おそらくあなたの場合、 s がファイルから読み取られ、 1 つずつcharキャストされます。したがって、最初に を読み取り、次にを読み取り、そこで停止します。wchar_t FFFE00getline(..., 0)

于 2010-04-28T15:18:13.860 に答える
0

L "ucs2-be.txt"は、私にはビッグエンディアンのフラグのように見えますが、配列FE FF 00 41 00 0D 00 0A0042はリトルエンディアンのように見えます。これが、FEFF文字がスキップされるのではなく配列に読み込まれた理由だと思います。ただし、wchar(0)の有無が結果に影響する理由はわかりません。

于 2010-04-28T00:12:48.110 に答える