读取过程中意外的EOF

Unexpected EOF during reading

本文关键字:EOF 意外 过程中 读取      更新时间:2023-10-16

我写了两个文件,一个是文本模式,一个是二进制模式,代码如下:

write.cpp

struct person {
    char name[20];
    int age;
    float weight;
};
int main(){
    ofstream output("data.txt");
    ofstream output2("data2.txt", ios::out|ios::binary);
    int i;
    person tmp;
    for (i=0; i<4; i++){
        cout<<"Write name: ";
        cin >> tmp.name;
        cout<<endl<<"age: ";
        cin >> tmp.age;
        cout<<endl<<"weight: ";
        cin >> tmp.weight;
        output.write((char*) &tmp, sizeof(tmp));
        output2.write((char*) &tmp, sizeof(tmp));
    }

    output.close();
    output2.close();
    getchar();
    return 0;
}

这两个文件是相同的(我也检查了十六进制编辑器)。

当我尝试用以下代码读取时,我在读取第一项后得到EOF:

read.cpp

int main(){
    bool found = false;
    int pos;
    person tmp;
    ifstream file("data.txt");
    if (!file) {
        cout << "Error";
        return 1;
    }
    while(!file.eof() && !found) {
        file.read( (char*) &tmp, sizeof(tmp));
        cout << "tmp.name: "<<tmp.name<<endl;
        cout << "EOF? "<<file.eof()<<endl;
        if (strcmp(tmp.name, "jack") == 0){
            found = true;
            //pos = file.tellg();
            //pos -= (int) sizeof(tmp);
        }
    }
    file.close();
    cout << endl <<"Press ENTER to continue...";
    getchar();
    return 0;
}

输出
tmp.name: Jacob
EOF? 1
found? 0

但是如果我将ifstream打开为二进制模式(ifstream file("data.txt", ios::in|ios::binary);),程序会找到我想要搜索的人。有人能解释我为什么它在二进制模式下工作,即使我在文本模式下写文件?

你没有说你在什么操作系统下,所以我只能推测,但是由于文本模式和二进制模式在Unix下是相同的,所以它是可能的窗口。在Windows下,文本模式有两个功能转换:它将单个'n'转换为两个字符CRLF行结束,并且在输入时,它将0x1A视为结束文件。根据你的描述,我猜你的数据不包含0x0A字节(将被视为'n'),因为十六进制比较是相同的,但它确实是包含一个0x1A字节,它被解释为文件结束。

一般来说,文本文件的正式规则是它们可以只包含可打印的字符,'t''n'等在'n'之前没有空格;在另外,它的实现定义了是否最终的'n'是否需要。总而言之,不能将二进制数据写入以文本模式打开的文件,并希望重新读取它。

同样,struct的布局和基本类型是实现定义的,并且可以(和)有时会从一个版本改变到另一个版本。这意味着如果你只使用ostream::write,你不能确定开始能够在将来重新读取数据(没有其他)程序可以确保重新阅读它)。这是有原因的ostream::write的参数是char const*,而不是void const*;ostream::write用于写入您拥有的数据自己格式化(可能是像XDR这样的二进制格式);不将内存一个字节一个字节地转储到文件中。

最后,在read进程中:使用file.eof()循环条件出错。利用的结果istream:read没有首先确保它的工作是未定义的行为。你的循环应该是类似以下语句:

Person tmp;
while ( file.read( ... ) && strcmp( tmp.name, "jack" ) != 0 ) {
    //  ...
}

1)

有人能解释我为什么它在二进制模式下工作,即使我在文本模式下写文件?

根据你的说法,当你在十六进制编辑器中查看它们时,这些文件是完全相同的,所以在这种情况下,无论你是以二进制模式还是文本模式编写它们都无关紧要。通常,在文本模式下,在Windows上将有秘密和背后的将换行从一个字节转换为两个字节。

2)你不应该在读取文件时使用file.eof()作为while条件——这太麻烦了。相反,您应该使用read语句作为条件语句:

while(file.read( (char*) &tmp, sizeof(tmp)) && !found)

你的程序在条件条件下使用。

你的演员:

(char*)

是C强制转换。你应该使用难看得多的c++强制转换:

reinterpret_cast<char*>(&tmp)

你可以把它想象成一个巨大的霓虹灯,表明一些非常疯狂的事情正在发生