2

这样做的规范方法是什么?

我必须在这里阅读 a 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 有一项法令禁止任何文件中存在空字节,我实际上不会感到惊讶。但显然 Vim 正在使用一些魔法将所有这些空值写入撤消文件格式。此外,如果您碰巧将内容编码或加密为随机字节流(或多种模拟采样),则必须产生空值。我的意思是,我可以继续前进:OS X 上的管道(FIFO)可以很好地处理通过它们的空字节:我可以 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

我首先使用常规字符串解决了这个问题。

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 回答
0

根本原因是它wstring不保存字节,而是宽字符。显然需要在字节和(宽)字符之间进行转换。就是这个翻译坏了。

如果要从二进制文件中读取字节,请将它们读入适当的容器中。例如std::vector<unsigned char>。如果您想从文本文件中读取(宽)字符,请继续使用当前代码。但是,混合它们是一个问题。

(这个建议适用于许多系统,即使它们可能会在不同的地方显示问题。特别是 Unix 在 ASCII 文本文件和二进制文件之间几乎没有区别,而 Windows 的 Unicode(UTF-16)文本文件和其在内存中的表示。)

于 2013-07-04T08:47:21.750 回答