Scott Meyers による本「Effective STL」には、テキスト ファイル全体を std::string オブジェクトに読み込む良い例があります。
std::string sData;
/*** Open the file for reading, binary mode ***/
std::ifstream ifFile (“MyFile.txt”, std::ios_base::binary); // Open for input, binary mode
/*** Read in all the data from the file into one string object ***/
sData.assign (std::istreambuf_iterator <char> (ifFile),
std::istreambuf_iterator <char> ());
8 バイト文字として読み取ることに注意してください。これは非常にうまく機能します。最近では、Unicode テキスト (つまり、1 文字あたり 2 バイト) を含むファイルを読み取る必要があります。ただし、次のように、データを Unicode テキスト ファイルから std::wstring オブジェクトに読み込むように (単純に) 変更しようとすると、次のようになります。
std::wstring wsData;
/*** Open the file for reading, binary mode ***/
std::wifstream ifFile (“MyFile.txt”, std::ios_base::binary); // Open for input, binary mode
/*** Read in all the data from the file into one string object ***/
wsData.assign (std::istreambuf_iterator <wchar_t> (ifFile),
std::istreambuf_iterator <wchar_t> ());
返された文字列は、ワイド文字ですが、代替のヌルがまだ含まれています。たとえば、ファイルに Unicode 文字列「ABC」が含まれている場合、ファイルのバイト (Unicode 先頭バイト 0xFF、0xFE を無視) は次のようになります。 <'A'> <0> <'B'> <0> <' C'> <0>
上記の最初のコード フラグメントは、次の (char) 文字列の内容を正しく結果として返します。
sData [0] = 'A'<br> sData [1] = 0x00
sData [2] = 'B'<br> sData [3 ] = 0x00
sData [4] = 'C'<br> sData [5] = 0x00
ただし、2 番目のコード フラグメントが実行されると、(wchar_t) 文字列の内容が次のような望ましくない結果になります。
wsData [0] = L'A'<br> wsData [1] = 0x0000
wsData [2] = L'B '<br> wsData [3] = 0x0000
wsData [4] = L'C'<br> wsData [5] = 0x0000
あたかもファイルがまだバイトごとに読み取られ、単に個々の wchar_t 文字に変換されているかのようです。
wchar_t に特化した std::istreambuf_iterator は、ファイルが一度に 2 バイトずつ読み取られるべきだと思っていたのではないでしょうか? そうでない場合、その目的は何ですか?
私はテンプレートにたどり着きました(簡単な偉業ではありません;-)、イテレータは実際にファイルをバイトごとに読み取り、それを内部の変換ルーチンに渡しているようです。 2 バイトを受信した後でのみ)。
この一見些細なタスクについて、Web 上の多くのサイト (このサイトを含む) を検索しましたが、この動作の説明や、必要と思われる以上のコードを必要としない適切な代替案は見つかりませんでした (例: A Google Web を検索すると、同じ 2 番目のコード フラグメントが実行可能なコードとして生成されます)。
動作することがわかった唯一のものは次のとおりです。これは、wstring の内部バッファーに直接アクセスする必要があり、それを型強制する必要があるため、チートであると考えています。
std::wstring wsData;
/*** Open the file for reading, binary mode ***/
std::wifstream ifFile (“MyFile.txt”, std::ios_base::binary); // Open for input, binary mode
wsData.resize (<Size of file in bytes> / sizeof (wchar_t));
ifFile.read ((char *) &wsData [0], <Size of file in bytes>);
ああ、避けられない「なぜファイルをバイナリ モードで開くのか、なぜテキスト モードで開くのか」という疑問を未然に防ぐために、ファイルがテキスト モード (デフォルト) で開かれたかのように意図的に開くということは、CR/LF ("\ r\n" または 0x0D0A) シーケンスは LF ("\n" または 0x0A) シーケンスに変換されますが、ファイルの純粋なバイト読み取りではそれらが保持されます。いずれにせよ、それらの頑固者にとって、それを変更しても、当然のことながら、何の効果もありませんでした.
ここで 2 つの質問があります。2 番目のケースが期待どおりに機能しないのはなぜですか (つまり、これらの反復子で何が起こっているのか)、そして Unicode 文字のファイルを wstring にロードする際のお気に入りの「コーシャ STL 方法」は何ですか? ?
ここで何が欠けていますか。それはばかげたものでなければなりません。
クリス