【问题标题】:why does ifstream read beyond eof? (even if no file is open) how to stop reading at eof?为什么ifstream读取超出eof? (即使没有打开文件)如何在 eof 处停止读取?
【发布时间】:2019-07-23 18:34:10
【问题描述】:

我只是在使用 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\...

}

【问题讨论】:

  • 要么在通过file.exceptions(std::ifstream::failbit); 设置失败位时指示流抛出,或者在执行seekg 之类的操作之前检查流的状态。就目前而言,您有未定义的行为。
  • 欢迎来到未定义的行为领域。你违反了合同,所以任何事情都可能发生。只需要在文件打开成功的情况下寻找这些操作,然后用file.seekg(0, file.end);寻找到最后,用tellg得到可以读取的大小。
  • @NathanOliver 谢谢,但我知道如何打开文件并获取大小。我仍然可以阅读 eof 之后的内容。所有这些路径文本都被读入。我只是想知道这是否会发生?如果我必须自己检查还剩多少空间?
  • seekg 不检查提供的输入,那是你的工作。如果你给它不好的输入,那么你得到的就是你得到的。如果你给它错误的值,你就会有未定义的行为。

标签: c++ io fstream ifstream eof


【解决方案1】:

为什么 ifstream 读取超出 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];
    }
}

【讨论】:

  • 谢谢。我实际上只是检查了一下,gcount 返回了 0。我注释掉了阅读并意识到我仍然拥有所有这些文本。大声笑(傻我)
  • 嘿,关于“你不能保证你得到size 字节”,如果你使用readsome 就不会了。根据cpprefcplusplus,它要么读取所有字符,否则将设置eofbit 和failbit。这意味着如果您想尝试使用它读取的任何数量,则必须进入上述 if 语句的else
  • @Puddle 你是对的。我不经常将原始read() 用于字节数组,我更习惯于使用std::string,所以我错过了。我的 if 语句看起来像这样:if (std::getline(file, string)) 因为这将读取到但不会超过文件末尾(因此不会设置错误标志)。无需额外检查。
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
相关资源
最近更新 更多