从文件中读取,奇怪的结局

时间:2012-06-11 17:03:13

标签: c++ printf ifstream

我找到了一段代码,它提供了文本文件的大小:

ifstream file("xmlfile.xml",ios::in);
//get size
file.seekg (0, ios::end);
int length = file.tellg();
file.seekg (0, ios::beg);

// allocate memory:
char* buffer = new char [length];

// read data as a block:
file.read (buffer,length);
file.close();
buffer[length-1] = '\0';
printf("%s",buffer);

问题在于我想要读取一个小的xml文件,完全读取它,但最后留下了许多'='符号,因为我发现它们等于文件中CR的数量。将EOL切换到Unix解决了这个问题,但为什么在Windows EOL中打印有问题?

示例xml:

<?xml version="1.0"?>
<catalog>




(EOL)

printf打印的是什么:

<?xml version="1.0"?>
<catalog>





══════

3 个答案:

答案 0 :(得分:3)

问题出现是因为Windows在每行的末尾使用了回车符+换行符,而Linux只使用其中一个。

您的ifstream以文字模式打开。它返回文本文件的绝对大小,但随后您指示它读取许多 text 字符。它似乎丢弃了Windows不会自动使用的额外字符,并且您最终会读取文件的末尾。

要纠正此问题,可以使用.gcount()来获取读取的字符数。

答案 1 :(得分:3)

有两个问题。

使用seektell获取文件大小将告诉您文件中有多少字节。光盘上的Windows EOL是两个字节。但是,当您在文本模式下打开的文件上使用read读取它时,EOL将在内存中变为一个字节。您可以通过以二进制模式打开文件来解决此问题:

ifstream file("xmlfile.xml",ios::in | ios::binary);

另一个问题是,如果要将文件的内容视为以空字符结尾的字符串,则需要为NULL终止符分配额外的空间。就目前而言,您将使用NULL覆盖文件的最后一个字节。你应该这样做:

char* buffer = new char [length+1];

buffer[length] = '\0';

答案 2 :(得分:2)

如果我理解正在发生的事情,tellg会告诉您位置以字节为单位,但在阅读过程中,Windows行结尾将转换为普通'\n';因此,buffer[length]引用的位置是在“缺失”CR数量的“真实”结束之后。

为避免此问题,请在读取文件后调用file.gcount()以获取上次读取时读取的字符数,并将其用作终止缓冲区的位置。