【问题标题】:Reading from file, strange ending从文件中读取,奇怪的结局
【发布时间】:2012-06-11 17:03:13
【问题描述】:

我找到了一个给出文本文件大小的 sn-p 代码:

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>





══════

【问题讨论】:

    标签: c++ printf ifstream


    【解决方案1】:

    有两个问题。

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

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

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

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

    和

    buffer[length] = '\0';
    

    【讨论】:

    • 我已经用 \0 终止了字符串,只是不是长度,而是长度 1
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 解决了这个问题,但还有为什么会一直留下'='呢?它不是一些没有被覆盖的奇怪符号
      • = 符号恰好是“未被覆盖的奇怪符号”。
      • @coolbartek 内存分配器在调试模式下通常会以特定模式填充内存。在释放模式下,您更有可能看到随机值。
      猜你喜欢
      • 1970-01-01
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      相关资源
      最近更新 更多