c++以二进制方式读取文件.文件结束的问题

C++ reading a file in binary mode. Problems with END OF FILE

本文关键字:文件 结束 问题 读取 二进制 方式 c++      更新时间:2023-10-16

我正在学习c++,我必须以二进制模式读取文件。我是这样做的(遵循c++参考):

unsigned values[255];
unsigned total;
ifstream in ("test.txt", ifstream::binary);
while(in.good()){
    unsigned val = in.get();
    if(in.good()){
        values[val]++;
        total++;
        cout << val <<endl;
    }
}
in.close();

所以,我每个字节读取文件,直到in.good()为真。为了了解发生了什么,我在while的末尾放了一些cout,下面是输出:

marco@iceland:~/workspace/huffman$ ./main 
97
97
97
97
10
98
98
10
99
99
99
99
10
100
100
10
101
101
10
221497852
marco@iceland:~/workspace/huffman$

现在,输入文件"test.txt"就是:

aaaa
bb
cccc
dd
ee

所以一切都很完美,直到最后,那里有221497852。我猜是文件末尾的问题,但是我想不出是什么问题。

我正在使用编辑&debian机器上的g++(64位)。如有任何帮助,我将不胜感激。

许多谢谢,

马可

fstream::get返回int值。这是问题之一。

其次,您正在读取二进制,因此您不应该使用格式化的流。你应该使用fstream::read:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream
int main () {
  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);
    char * buffer = new char [length];
    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
    is.read (buffer,length);
    if (is)
      std::cout << "all characters read successfully.";
    else
      std::cout << "error: only " << is.gcount() << " could be read";
    is.close();
    // ...buffer contains the entire file...
    delete[] buffer;
  }
  return 0;
}

这不是istream::get()的设计使用方式。使用这个函数的经典习惯用法是:

for ( int val = in.get(); val != EOF; val = in.get() ) {
    //  ...
}

或者更习惯的:

char ch;
while ( in.get( ch ) ) {
    //  ...
}

第一个循环实际上继承自C语言,其中in.get()是相当于fgetc() .

尽管如此,据我所知,你给的代码应该工作。这不是习惯用法,也不是

c++标准不清楚如果读取的字符值为负。fgetc()需要一个值范围是[0...UCHAR_MAX],我认为可以安全地假设这里是intent。这是,至少,什么我用过的实现。但这并不影响你的输入。的实现如何解释标准,in.get()的返回值必须在范围内[0...UCHAR_MAX][CHAR_MIN...CHAR_MAX],否则必须为EOF(通常为1)。(我很确定其意图的原因是需要[0...UCHAR_MAX]是因为,否则,您可能不需要能够区分文件结束和有效字符。)

如果返回值是EOF(几乎总是)-1), failbit应该设置,所以in.good()将返回false。没有允许使用in.get()的情况返回221497852。这是我能想到的唯一解释你的结果是你的文件有一些字符位7设置在文件的末尾,表示实现是为this返回一个负数(但不是文件结束),因为它是一个字符),这会导致越界values[val]中的索引,并且该索引是越界索引最终修改了val。或者你的实现是当它返回end of时,没有设置failbit文件。

可以肯定的是,我很想知道你从如下:
std::ifstream in( "text.txt", std::ios_base::binary );
int ch = in.get();
while ( ch != std::istream::traits_type::eof() ) {
    std::cout << ch << std::endl;
    ch = in.get();
}

这避免了任何可能无效索引和任何类型的问题转换(尽管intunsigned的转换很好)定义)。另外,出于好奇(因为我只能访问vc++)在这里),您可以尝试替换in如下:

std::istringstream in( "nxE5" );

我希望得到:

10
233

(假设8位字节和基于ASCII的代码集。这两个)

我终于弄明白了。显然,问题似乎不是由于任何代码。问题已经解决了。它总是在文件末尾追加一个换行符。其他编辑器(如vim)也会出现这种情况。对于某些编辑器,这可以配置为不附加任何内容,但在gedit中,这显然是不可能的。https://askubuntu.com/questions/13317/how-to-stop-gedit-gvim-vim-nano-from-adding-end-of-file-newline-char

为每个问我的人干杯

马可