提问人:Puddle 提问时间:7/24/2019 更新时间:7/24/2019 访问量:1649
为什么 IFSTREAM 读取 Beyond EOF?(即使没有打开文件) 如何在EOF停止读取?
why does ifstream read beyond eof? (even if no file is open) how to stop reading at eof?
问:
我只是在使用 fstream 测试一些 IO 安全检查,并注意到我在向外寻找时没有得到任何标志(我预计 EOF,但我意识到标志仅在 IO 操作后设置?),当尝试读取超出文件大小时,我希望它会停在 EOF,但它继续从某个未知来源读取。最后,我注意到你甚至不需要打开文件。我是否必须自己手动应用数学,以便它不会读取过去的 EOF?以及它如何/为什么/在哪里读取文件?
#include <iostream>
#include <fstream>
void checkErrors(std::ifstream& f){
std::cout<<"FLAGS: ";
if(f.good()) std::cout<<"good";
if(f.rdstate() & f.badbit) std::cout<<"badbit ";
if(f.rdstate() & f.eofbit) std::cout<<"eofbit ";
if(f.rdstate() & f.failbit) std::cout<<"failbit ";
std::cout<<std::endl;
}
int main(){
std::ifstream file;
// file.open("abc.txt"); // don't even have to open any file
file.seekg(100, file.beg); // can seek outside file
std::cout<<file.tellg()<<std::endl; // 100 (if open else) -1
checkErrors(file); // FLAGS: good (if open else) failbit
int size = 200;
char* data = new char[size];
file.read(data,size); // can read outside file
checkErrors(file); // FLAGS: eofbit failbit (if open else) failbit
for(int i=0; i<size; i++)std::cout<<data[i]; // PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\Windows\...
}
答:
3赞
Martin York
7/24/2019
#1
为什么 IFSTREAM 读取 Beyond EOF?
我敢肯定它不会。
你是在问为什么在你超越终点之后不是真的吗?bad()
(即使没有打开文件) 如何在EOF停止读取?
如果您尝试读取文件末尾,则会出现错误。仅仅超越终点本身是不够的。但是,在超出终点之后尝试访问数据应该会导致错误。
好吧,你看这里有一个错误:
file.read(data,size); // can read outside file
for(int i=0; i<size; i++)std::cout<<data[i]; // PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\Windows\...
这应该写成:
if (file.read(data, size)) {
// If you attempt to read and it works then you can print out
// the data you read otherwise what is the point.
// Also notice you can't gurantee that you got `size` bytes.
// You should consult `gcount()` to get the number of characters read.
for(int i = 0; i < file.gcount(); ++i) {
std::cout << data[i];
}
}
评论
1赞
Puddle
7/24/2019
谢谢。我真的只是检查了一下,gcount 返回 0。我注释掉了阅读内容,并意识到我仍然拥有所有这些文本。哈哈(傻傻的我)
0赞
Puddle
7/30/2019
嘿,再说一遍,关于“你不能保证你有字节”,如果你使用的话,不是吗。根据 CPpref 和 CPlusPlus,它将读取所有字符,否则将设置 eofbit 和 failbit。这意味着,如果您想尝试使用它读取的任何数量,则必须进入上述 if 语句。size
readsome
else
0赞
Martin York
7/30/2019
@Puddle 你是对的。我不经常使用我更习惯使用的 raw 到字节数组,所以我错过了。我的 if 语句如下所示:因为这将读取到但不会超过文件的末尾(因此不会设置坏标志)。使这种额外的检查变得没有必要。read()
std::string
if (std::getline(file, string))
评论
file.exceptions(std::ifstream::failbit);
seekg
file.seekg(0, file.end);
tellg
seekg
不检查提供的输入,那是你的工作。如果你给它不好的输入,那么无论你从中得到什么,你得到的就是你得到的。如果你给它一个坏的值,你就有未定义的行为。