2

これを行う標準的な方法は何ですか?

ここで を読むwstring必要がありますが、答えも当てはまるはずですstring

これが私が今試していることです:

wifstream file(filename, ios::in | ios::binary);
// this next line is cleverer but works the same way (i.e. null byte stops it)
// return wstring(istreambuf_iterator<wchar_t>(file), istreambuf_iterator<wchar_t>());
wstring out;
wchar_t buf[8192];
while (true) {
    file.read(buf, 8192);
    streamsize len = file.gcount();                                       
    cerr << len << "chars read.";                                         
    out.append(buf, len);                                                 
    if (len != 8192) break;                                               
}                                                                         
return out;

ファイルでヌルバイトに遭遇したら、どうすれば読み続けることができますか?

POSIX に null バイトがこれまでのファイルに存在することを禁止する法令があったとしても、私は実際には驚かなかったでしょう。しかし明らかに、Vim はいくつかの魔法を使ってこれらすべてのヌルを undo ファイル形式に書き込んでいます。また、何かをランダムなバイトストリーム (または多くの種類のアナログサンプリング) にエンコードまたは暗号化すると、null が発生する必要があります。OS X のパイプ (FIFO) は、パイプを通過する null バイトを問題なく処理します。undofile を cat し、それを xxd にパイプして、それを読み取ることができます。

これは明らかに、私がつまずいているある種の単純なことです。それは何ですか?確かにそれを行うC++の方法があります。または、 を使用する方法を知っているかもしれません<stdio.h>。私は知りたいです。

たとえば、ここに私がテストしているファイルがあります:

% cat .dmp.cpp.un\~| xxd | head                                   
0000000: 5669 6d9f 556e 446f e500 0218 96c6 25f6  Vim.UnDo......%.
0000010: 64bb 2301 6ed8 3578 5c50 61e0 eae5 a819  d.#.n.5x\Pa.....
0000020: b17d 53b5 f932 dc9d 40aa 1b00 0000 8500  .}S..2..@.......
0000030: 0000 5720 2020 2020 2020 2020 2020 2063  ..W            c
0000040: 6572 7220 3c3c 2022 466f 756e 6420 616e  err << "Found an
0000050: 2075 6e70 7269 6e74 6162 6c65 2063 6861   unprintable cha

バイト 2b は最初のヌルバイトです。プログラムは 44 バイト (2c) を読み取るため、最初のヌル バイトを書き込み、そこで停止します。

% la .dmp.cpp.un\~
-rw-r--r--  1 lust  staff  326836 Jul  4 01:41 .dmp.cpp.un~

PS、ここからのコメントでそのきちんとしたワンライナーを取得しました。悲しいことに、この問題にも苦しんでいます。

4

2 に答える 2

0

根本的な原因は、wstringバイトではなくワイド文字を保持することです。明らかに、バイトと (ワイド) 文字の間の変換が必要です。壊れるのはこの翻訳です。

バイナリ ファイルからバイトを読み取る場合は、それらを適切なコンテナーに読み取ります。例std::vector<unsigned char>。テキスト ファイルから (ワイド) 文字を読み取りたい場合は、現在のコードを使用してください。ただし、それらを混在させることは問題です。

(このアドバイスは、さまざまな場所で問題が発生する可能性がありますが、多くのシステムに当てはまります。特に、Unix では ASCII テキスト ファイルとバイナリ ファイルの区別がほとんどありませんが、Windows では、Unicode (UTF-16) テキスト ファイルとバイナリ ファイルでは問題が少ない傾向があります。そのインメモリ表現。)

于 2013-07-04T08:47:21.750 に答える
0

最初に通常の文字列を使用して問題を回避しました。

ifstream file(filename, ios::in | ios::binary);
wstring out;
char buf[8192];
while (true) {
    file.read(buf, 8192);
    streamsize len = file.gcount();
    cerr << len << "chars read.";
    string s(buf, len);
    out.append(s.begin(), s.end());
    if (len != 8192) break;
}
return out;
于 2013-07-04T07:45:44.487 に答える