【问题标题】:rdbuf() reading junkrdbuf() 读取垃圾
【发布时间】:2012-11-29 20:33:51
【问题描述】:

使用此代码,我从文件中读取了一个字符串。

pbuf = infile.rdbuf();
size = pbuf->pubseekoff(0, ios::end, ios::in);
pbuf->pubseekpos (0,ios::in);
buf = new char[size];
pbuf->sgetn(buf, size);
str.assign(buf, buf+size);

我必须读取临时变量 char* buff 中的数据,因为 sgetn 需要 char* 而不是 string
所以在问我的实际问题之前,如果有人知道更好的阅读方式文件中可能包含空格字符的字符串请告知(直到 eof 才循环)。

文件内容为:
呜呜呜
废话换行

但我得到的是:
呜呜呜
废话换行═

玩弄代码后,我注意到奇怪字符的数量增加了,因为我添加了更多\n 字符。似乎当我尝试获取文件大小时,每个 \n 字符占用 2 个字节的空间,但在字符串中它只占用 1 个字节,因此我的字符串看起来很奇怪。我该如何避免这种情况?

【问题讨论】:

  • 这可能是因为 CRLF Windows 样式的行尾,而字符串只包含 CR...
  • 从 C++11 开始,您可以使用 &s[0] 直接读入 string,并且它可以在一些 C++11 之前的实现(如 MSVC)中实际工作。
  • @ybungalobill 是 s 一个字符串吗?
  • @AtoMerZ:是的。假设你resized当然是正确的......关键是现在保证它在内存中是连续的,并且禁止写入时复制。所以现在这样做是安全的。 编辑啊,MSVC10 调试 CRT 也引入了一个错误,该错误会在索引到字符串的末尾元素时触发断言(尽管标准允许这样做)。所以只有size() > 0.

标签: c++ file fstream


【解决方案1】:

在 Windows 上,文本文件中的行尾表示为两个字节:0x0d、0x0a。当您使用文本模式从此类文件中读取时,这两个字节将被转换为单个字符 '\n'。当您使用二进制模式时,您正在读取原始字节,并且它们不会为您翻译。如果您不想要它们,则必须自己进行翻译。

【讨论】:

  • OP 不使用格式化输入...根据您打开文件的方式(带或不带 ios_base::binary 标志)在较低级别上完成翻译。
【解决方案2】:

这是由于标准库实现将标准 windows 行以 \r\n 结尾变成了标准 c++ 行以 \n 结尾。

正如@ipc 所说,您可以使用this answer 做您想做的事。 (注意:根据 cmets 的说法,该问题的公认答案实际上并不是最好的方法。)

或者,您可以通过以二进制模式打开流来禁用行尾转换,如下所示:

std::ifstream t(fileName, std::ios_base::in | std::ios_base::binary);

【讨论】:

  • 虽然这样确实解决了奇数的问题,但还是有一点小问题。它仍然为额外的字符分配空间,因为tellg() 返回文件开头的字节数。
  • 哈哈哈!这并不能完全解决问题,但现在我阅读了这两个字符,没有浪费空间。
  • @AtoMerZ 重要的是准确地知道文本有多长,例如,如果您需要插入一个空终止符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2014-12-21
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
相关资源
最近更新 更多