2013-05-01 263 views
4

我试图使用ifstream读取3GB数据文件,它给了我错误的文件大小,而当我读取600MB文件时,它给了我正确的结果。除了错误的文件大小之外,我也无法使用ifstream读取整个文件。ifstream :: 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 

它看起来对我来说,它达到一定的限制。

我在Windows计算机上使用Visual Studio 2010测试代码,该计算机具有大量内存和磁盘空间。

我想读取一些大文件。如果ifstream无法读取大文件,那么使用哪种流式阅读器?

+1

我注意到你直接调用_wstat64。你在编译32位二进制文​​件吗?你是否尝试过64位二进制文​​件进行ifstream测试? – WhozCraig 2013-05-01 19:24:06

+0

@WhozCraig:如果文件系统没有,32位代码应该能够处理超过2GB的文件,如果不是这是一个非常糟糕的错误。 – 2013-05-01 19:26:55

+0

@BenVoigt我同意,如果在32位实现中'stat()'(而不是'_wstat64()')的行为相似,并且在64位实现中'ifstream'行为*不同*,我只是好奇而已。 – WhozCraig 2013-05-01 19:29:18

回答

6

我想你想说:

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

至少这可以正常工作,因为我已经奠定周围6GB的文件。但是我正在使用Visual Studio 2012进行编译。即使您的原始代码在该环境下也能正常工作。

因此,我怀疑这是VS 2010中的std库中的一个bug,它在VS 2012中得到了修复。无论是pos_type的运算符重载中的错误还是该类不是64位的,都是未知的。我不得不安装VS 2010来验证,但这可能是问题所在。

+0

根据标准,它看起来不像'fpos :: state_type>'(由'tellg()'返回的类型应该有一个公共的'seekpos()'成员这是一个实现 - 具体的扩展? – 2013-05-01 19:35:05

+0

是的,它确实解决了这个问题,现在我得到了正确的结果 – veda 2013-05-01 19:37:55

0

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

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

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

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

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

示例2:
编译器可以使用32位作为文件位置变量,但OS使用24位。在这个例子中,OS是限制因素。

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

+0

我认为你的意思是标准库,而不是编译器......但标准库只能是限制因素,如果你不是使用适合操作系统的库 – 2013-05-01 19:33:40

+0

标准库是否确定'filepos'变量或编译器的大小?我知道'size_t'的长度是由编译器设置的 – 2013-05-02 01:26:24

+0

标准库确实。文件位置没有被指定为'size_t'或'ssize_t',并且通常不应该是,因为文件系统限制大大超过指针限制(即使在64位系统上,文件系统开始使用1 28位长度!)。 – 2013-05-02 02:16:38

4

我修改你稍微代码,东西会编译:

#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技嘉文件。随着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位有符号数,所以它们对iostreams的实际限制可能是2千兆字节。随着VS 2012,这显然已得到纠正。