读取过程中意外的EOF
Unexpected EOF during reading
我写了两个文件,一个是文本模式,一个是二进制模式,代码如下:
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)
你可以把它想象成一个巨大的霓虹灯,表明一些非常疯狂的事情正在发生
- 如何确定我已使用非编码文件到达 EOF?
- 在C++中对T*类型执行std::move的意外行为
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 处理除以零会导致<csignal>意外行为
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 使用vscode调试时,GDB意外退出
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 尝试将字符串/字符转换为整数会产生意外结果
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标头错误 C2238 意外标记";"
- C++中意外的多头值
- vector.size() 在比较中意外工作
- 使用 malloc() 时出现意外大小
- "错误 C0000:语法错误,令牌"<EOF>"处出现意外$end,并且不确定
- 文件设置正确,但eof()和peek()意外地从新流返回了错误的值
- 无法编译顶点着色器:令牌"<EOF>"出现意外$end
- 读取过程中意外的EOF