【问题标题】:ifstream:: What is the maximum file size that a ifstream can readifstream:: ifstream 可以读取的最大文件大小是多少
【发布时间】:2013-05-01 19:16:15
【问题描述】:

我尝试使用 ifstream 读取一个 3GB 的数据文件,但它给了我错误的文件大小,而当我读取一个 600MB 的文件时,它给了我正确的结果。除了错误的文件大小,我也无法使用 ifstream 读取整个文件。

这是我使用的代码

        std::wstring name;
        name.assign(fileName.begin(), fileName.end());
        __stat64 buf;
        if (_wstat64(name.c_str(), &buf) != 0)
            std::cout << -1; // error, could use errno to find out more

        std::cout << " Windows file size : " << buf.st_size << std::endl;;


        std::ifstream fs(fileName.c_str(), std::ifstream::in | std::ifstream::binary);
        fs.seekg(0, std::ios_base::end);

        std::cout << " ifstream  file size: " << fs.tellg() << std::endl;

3GB 文件的输出是

 Windows file size : 3147046042
 ifstream  file size: -1147921254

而 600 MB 文件的输出是

 Windows file size : 678761111
 ifstream  file size: 678761111

以防万一,我还测试了 5GB 文件和 300 MB 文件,

5GB 文件的输出是

Windows file size : 5430386900
 ifstream  file size: 1135419604

300MB 文件的输出是

Windows file size : 318763632
 ifstream  file size: 318763632

在我看来它已经达到了某个极限。

我正在使用 Visual Studio 2010 在具有大量内存和磁盘空间的 Windows 机器上测试代码。

我正在尝试读取一些大文件。如果 ifstream 无法读取大文件,使用哪种流式阅读器比较好?

【问题讨论】:

  • 我注意到您正在直接调用 _wstat64。你在编译 32 位二进制文​​件吗?您是否为 ifstream 测试尝试了 64 位二进制文​​件?
  • @WhozCraig:如果文件系统可以处理超过 2GB 的文件,32 位代码应该能够处理,否则这是一个非常糟糕的错误。
  • @BenVoigt 我同意,我只是好奇stat()(不是_wstat64())在 32 位实现上的行为是否相似,以及 ifstream 在64位实现。
  • @WhozCraig:我正在编译的平台是 Win32。我没有尝试 64 位二进制。

标签: c++ stl ifstream


【解决方案1】:

我想你想说:

std::cout << " ifstream  file size: " << fs.tellg().seekpos() << std::endl;

至少对于我放置的 6GB 文件来说,这可以正常工作。但我正在使用 Visual Studio 2012 进行编译。甚至您的原始代码在该环境下也可以正常工作。

所以我怀疑这是 VS 2010 上的 std 库中的一个错误,该错误已在 VS 2012 中得到修复。是否是 pos_type 的运算符重载中的一个错误,或者该类是否不支持 64 位是未知的。我必须安装 VS 2010 才能验证,但这可能是问题所在。

【讨论】:

  • 根据标准,它看起来不像fpos&lt;char_traits&lt;char&gt;::state_type&gt;tellg() 返回的类型应该有一个公共seekpos() 成员。这是一个特定于实现的扩展吗?
  • 是的,它确实解决了问题。现在我得到了正确的结果。
  • 请注意,MS 在 Visual Studio 15.8 中弃用了 seekpos(),他们还将实现更改为始终返回 0。
【解决方案2】:

我稍微修改了您的代码,使其可以编译:

#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>

int main() { 

    std::wstring name(L"whatever.txt");

    __stat64 buf;
    if (_wstat64(name.c_str(), &buf) != 0)
        std::cout << -1; // error, could use errno to find out more

    std::cout << " Windows file size : " << buf.st_size << std::endl;;


    std::ifstream fs(name.c_str(), std::ifstream::in | std::ifstream::binary);
    fs.seekg(0, std::ios_base::end);

    std::cout << " ifstream  file size: " << fs.tellg() << std::endl;

    return 0;
}

我在一个 ~3 GB 的文件上试过这个。使用 VS 2012(32 位或 64 位)它产生了:

 Windows file size : 3581853696
 ifstream  file size: 3581853696

使用 32 位 VS 2008(抱歉,目前没有安装 VS 2010 的副本)我得到了:

 Windows file size : 3581853696
 ifstream  file size: -713113600

因此,旧版本的 VS/VC++ 似乎使用 32 位有符号数来表示文件大小,因此它们对 iostream 的实际限制可能是 2 GB。在 VS 2012 中,这显然已得到纠正。

【讨论】:

    【解决方案3】:

    最大文件大小由编译器和操作系统决定。

    编译器可以控制用于访问文件大小的变量的大小。

    操作系统决定了它可以支持的最大文件大小。

    C++ 语言不限制文件大小。

    示例 1:
    编译器可以为文件位置变量分配 16 位,而操作系统可以为最大文件大小使用 32 位指针。在这种情况下,编译器是限制因素。

    示例 2:
    编译器可以为文件位置变量使用 32 位,但操作系统使用 24 位。在此示例中,操作系统是限制因素。

    总之,最大文件大小取决于编译器和操作系统。

    【讨论】:

    • 我认为您的意思是标准库,而不是编译器......但如果您没有使用适合操作系统的库,标准库只能成为限制因素。
    • 标准库是否确定filepos 变量或编译器的大小?我知道size_t 的长度是由编译器设置的。
    • 标准库可以。用于文件位置的类型未指定为size_tssize_t,通常不应该,因为文件系统限制大大超过指针限制(即使在文件系统开始使用 128 位的 64 位系统上)长度!)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2011-01-26
    • 2013-01-14
    相关资源
    最近更新 更多