2

我找到了一段代码,它给出了一个文本文件的大小:

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>





══════
4

3 回答 3

3

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

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

为了纠正这个问题,可以使用 .gcount() 来获取读取的字符数。

于 2012-06-11T17:11:07.697 回答
3

有两个问题。

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

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

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

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

buffer[length] = '\0';
于 2012-06-11T17:17:16.663 回答
2

如果我正确理解发生了什么,tellg会告诉您以 bytes 为单位的位置,但在读取期间,Windows 行尾将转换为纯'\n'; 正因为如此,所指的位置buffer[length]是在“丢失” CR 数量的“真实”结尾之后。

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

于 2012-06-11T17:10:59.113 回答