【问题标题】:Ifstream read fails at a specific size (unrelated to file size)Ifstream 读取在特定大小处失败(与文件大小无关)
【发布时间】:2015-09-02 18:20:21
【问题描述】:

我正在尝试读取一个文件,但我意识到它会失败,因为我会尝试读取太多数据,即使该文件比我要读取的文件大得多。

文件为 120 MB,我的 ifstream 在 12967 字节处失败(即使它在 12801 处开始表现怪异。

这是说明我的问题的代码:

#include <fstream>
#include <iostream>
#include <Windows.h>

using std::ifstream;
using std::cout;

#define CORRECT_SIZE 12800
#define CORRECT_BUT_WIERD 12966
#define INCORRECT_SIZE 12967

bool check_error_bits(ifstream* f);

int main()
{
    ifstream myFile("myfile.txt");
    char c[CORRECT_SIZE];
    char c2[CORRECT_BUT_WIERD];
    char c3[INCORRECT_SIZE];

    /*
     * TEST A (works fine)
    */
    myFile.seekg(0, std::ios_base::beg);
    myFile.read(c, CORRECT_SIZE);
    check_error_bits(&myFile);
    cout << myFile.tellg() << std::endl; // Here, tellg() returns 12800

    /*
     * TEST B (works too, but acts wierd)
     */
    myFile.seekg(0, std::ios_base::beg);
    myFile.read(c2, CORRECT_BUT_WIERD);
    check_error_bits(&myFile);
    cout << myFile.tellg() << std::endl; // Here, tellg() returns 16896

    /*
     * TEST C (FAIL)
    */
    myFile.seekg(0, std::ios_base::beg);
    myFile.read(c3, INCORRECT_SIZE);
    check_error_bits(&myFile);
    cout << myFile.tellg() << std::endl; // Here, tellg() returns -1

    system("pause");
}

bool check_error_bits(ifstream* f)
{
    bool stop = false;

    if (f->eof())
    {
        char msg[500];
        strerror_s(msg, errno);
        cout << "1: " << msg << std::endl;
    }

    if (f->fail())
    {
        char msg[500];
        strerror_s(msg, errno);
        cout << "2: " << msg << std::endl;
        stop = true;
    }

    if (f->bad())
    {
        char msg[500];
        strerror_s(msg, errno);
        cout << "3: " << msg << std::endl;
        stop = true;
    }

    return stop;
}

尝试读取少于 12800 字节的内容效果很好。从 128001 到 12966,它可以工作(虽然我没有检查数据是否正确),但是tellg() 返回无意义。在 12966 之后,读取完全失败。

该程序的控制台输出是:

12800
16896
1: No error
2: No error
-1
Press any key to continue . . .

任何帮助将不胜感激!

【问题讨论】:

  • 我假设您使用 VC++ 作为编译器,来自 包含。你是编译成 64 位还是 32 位?
  • 32 位,我认为这么低的数字没关系?
  • 可能不是,但它属于“很高兴知道”的类别
  • @MyUsername112358 您在调试时究竟观察到了什么?我想你做到了。
  • 提示:在 myFile 构造函数中添加“ios::binary”;转储文件的 16895-16897 字节;在每次测试之间关闭和打开文件。

标签: c++ ifstream


【解决方案1】:

在 Windows 环境和文本文件中,值 26=0x1A=^Z 的字符被视为“结束 fo 文件”。

因此,如果文件没有以二进制形式打开,即使文件更大,也会收到意外的 eof。

参见维基百科“文件结尾”(https://en.wikipedia.org/wiki/End-of-file):

在 Microsoft 的 DOS 和 Windows(以及 CP/M 和许多 DEC 操作系统)中,从终端读取永远不会产生 EOF。相反,程序识别源是终端(或其他“字符设备”)并将给定的保留字符或序列解释为文件结束指示符;最常见的是 ASCII Control-Z,代码 26。

【讨论】:

    【解决方案2】:

    您有一个 16,896 字节的文件。第一次阅读工作正常。第二次读取遇到文件结尾,只能读取 16,896 个字节。您的第三次读取失败,因为您没有清除流中的文件结束标志。

    您可能还有一个 120MB 的文件,但这无关紧要。检查代码中文件的大小。 (或者它可能是 120MB 的二进制数据,但您正在以文本模式读取它。)

    【讨论】:

    • 文件大小为 120 MB...远大于 16896 字节。
    • @MyUsername112358 你是怎么确定的?尽可能精确。
    • myFile.seekg(0, std::ios_base::end); cout
    • 读取二进制文件可以正常工作,但为什么呢?文本模式下的 1 个字节与二进制模式下的 1 个字节不一样吗?
    • 以 ascii 模式读取文件意味着读取数据并返回操作系统决定的任何内容。
    【解决方案3】:

    你写的

    (虽然我没有检查数据是否正确)

    这样做,因为我认为数据是正确的。

    我假设您使用的是 Windows,所以: Why can't Explorer decide what size a file is?

    还有https://superuser.com/questions/567175/why-is-the-folder-size-in-properties-different-from-the-total-file-folder-size

    【讨论】:

    • 我知道 WIndows 无法准确显示文件大小,但我自己制作了这个文件,它比 16,896 字节大。 (大约 120 MB)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    • 2016-04-01
    • 1970-01-01
    • 2023-03-28
    • 2015-08-07
    • 2015-01-20
    • 2013-12-28
    相关资源
    最近更新 更多