如何在C ++中检查ifstream是否到达文件结尾

16

我需要按顺序读取一个大文件的所有块(约10GB),该文件包含许多浮点数和一些字符串,就像这样(每个项目由“\n”分隔):

6.292611 -1.078219E-266 -2.305673E+065 sod;eiwo 4.899747e-237 1.673940e+089 -4.515213

每次读取MAX_NUM_PER_FILE个项目,并对它们进行处理并写入另一个文件,但是我不知道何时结束ifstream。 这是我的代码:

ifstream file_input(path_input);  //my file is a text file, but i tried  both text and binary mode, both failed.
if(file_input)
{
    file_input.seekg(0,file_input.end);
    unsigned long long length = file_input.tellg();    //get file size
    file_input.seekg(0,file_input.beg);

    char * buffer = new char [MAX_NUM_PER_FILE+MAX_NUM_PER_LINE];
    int i=1,j;
    char c,tmp[3];
    while(file_input.tellg()<length)
    {
        file_input.read(buffer,MAX_NUM_PER_FILE);
        j=MAX_NUM_PER_FILE;
        while(file_input.get(c)&&c!='\n')
            buffer[j++]=c;   //get a complete item

        //process with buffer...

        itoa(i++,tmp,10);    //int2char
        string out_name="out"+string(tmp)+".txt";
        ofstream file_output(out_name);
        file_output.write(buffer,j);
        file_output.close();
    }

    file_input.close();
    delete[] buffer;
}

我的代码出了问题,length比实际文件大小还大。我尝试使用file_input.good()或者!file_input.eof(),但它们都没有起作用。getline(file_input, s)是好的,但比read慢得多,我想使用read,但我不知道如何检查是否已到达ifstream的文件结尾。

我在Windows 7上使用VS2010工作。

我已经搜索过了,但没有找到任何关于这个问题的答案,How to open a file using ifstream and keep reading it until the end 这个链接无法回答我的问题。


更新,问题已解决

大家好,我已经发现这是我的问题。同时while(file_input.tellg()<length)while(file_input.peek()!=EOF)都可以正常工作!推荐使用while(file_input.peek()!=EOF)

在文件结尾处写入的额外内容是上一次中buffer中剩余的内容。

以下是正确的代码:

ifstream file_input(path_input);
if(file_input)
{
    //file_input.seekg(0,file_input.end);
    //unsigned long long length = file_input.tellg();   //get file size
    //file_input.seekg(0,file_input.beg);

    char * buffer = new char [MAX_NUM_PER_FILE+MAX_NUM_PER_LINE];
    int i=1,j;
    char c,tmp[3];
    while(file_input.peek()!=EOF)
    {
        memset(buffer,0,sizeof(char)*(MAX_NUM_PER_FILE+MAX_NUM_PER_LINE));  //clear first!
        file_input.read(buffer,MAX_NUM_PER_FILE);
        j=MAX_NUM_PER_FILE;
        while(file_input.get(c)&&c!='\n')
            buffer[j++]=c;

        itoa(i++,tmp,10);//int2char
        string out_name="out"+string(tmp)+".txt";
        ofstream file_output(out_name);
        file_output.write(buffer,strlen(buffer));   //use the correct buffer size instead of j
        file_output.close();
    }

    file_input.close();
    delete[] buffer;
}

2
在读取之前不应该检查EOF。尝试读取并检查是否成功。 - The Paramagnetic Croissant
@TheParamagneticCroissant 你是指 while(file_input.read(buffer,MAX_NUM_PER_FILE)) 吗?我尝试过了,但它可以读取整个文件,有一些项目没有被读取。 - user1024
@MSalters 我认为链接的问题实际上并没有回答这个问题。 - Pixelchemist
看来我从可能重复的列表中选择了错误的问题,这个列表实际上相当大。请参见例如 https://dev59.com/NW035IYBdhLWcg3wJcYv?lq=1 (关于 .eof() 的最高票问答)。 - MSalters
另一个 STL 设计失败的指标,就好像询问大小或流的结尾太过离奇。 - Sam Ginrich
1个回答

30
while( file_input.peek() != EOF )
{
    // code
}

基本上,peek()会读取下一个char,但不会提取它。

所以你可以将其与EOF进行比较。


就像 while(file_input.tellg()<length) 一样,它仍然会在文件结束后获取更多错误的 char - user1024
1
抱歉,是我的错。你的解决方案有效,见我的更新。谢谢。 - user1024
这对于以read | write模式打开的二进制文件也适用吗?它是否适用于所有二进制流? - Violet Giraffe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接