2012-11-29 64 views
1

使用此代码我从文件中读取一个字符串。rdbuf()阅读垃圾

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)。

文件的内容是:
等等等等
等等在新线等等

但我得到的是:
等等等等
等等在新line═

嗒嗒

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

+1

[将整个ASCII文件读入C++ std :: string](http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring) – ipc

+1

这可能是因为CRLF Windows风格线结束,而字符串只持有CR ... –

+0

由于C++ 11,您可以使用'&s [0]'直接读入'string',并且它在一些预C++ 11实现(如MSVC)。 – ybungalobill

回答

1

这是由于标准库实现将标准windows行结尾\r\n转换为结尾\n的标准C++行。

正如@ipc所说,您可以使用this answer来做你想做的事。 (注意:根据评论,对这个问题的接受答案实际上并不是实现它的最好方法。)

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

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

虽然这确实解决了奇怪字符的问题,但它仍然有一个小问题。它仍然为额外的字符分配空间,因为'tellg()'返回文件开头的字节数。 – atoMerz

+0

@AtoMerZ以二进制模式打开文件应该可以解决这个问题。 – Dan

+0

哈哈哈!这并不能完全解决问题,但现在我读了两个角色,没有浪费空间。 – atoMerz

2

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

+0

OP不使用格式化输入...根据您打开文件的方式(带有或不带有ios_base :: binary标志),在较低级别上完成翻译。 – ybungalobill

+0

@ybungalobill - 谢谢。固定。 –