如何使用c ++中的fstream将数据写入大于2GB的文件

时间:2015-05-30 02:24:55

标签: c++ curl fstream

我搜索过TON,找到一种方法,使用fstream或其他方法,将数据写入大文件,但没有找到任何答案。

我的问题是,我从互联网上下载数据,然后将数据写入预先分配的文件。对于小于2GB的文件,一切似乎都没问题,但是当使用大于2GB的预分配文件进行尝试时,将流指针移动到预分配文件中的特定位置(例如文件的最后位置)时会出错写数据,似乎无法做到,tellp allway返回-1。

这是我的写入数据方法,因为写入预分配文件,我不使用FILE或boost:iosstream。我使用Visual Studio 2008和.Net 3.5。感谢阅读并帮助我^。^

size_t writeData(void *ptr, size_t size, size_t nmemb, Downloader *objDownloader){
    size_t written;     

    if (objDownloader->_stop == false && objDownloader->mystream.is_open()){

        objDownloader->mystream.seekp(objDownloader->_posSeek, ios::beg);           
        written=size * nmemb;
        objDownloader->mystream.write(static_cast<char*>(ptr), written);

        objDownloader->_posSeek += size*nmemb;
        objDownloader->_downloaded += size*nmemb;

        objDownloader->mystream.seekp(objDownloader->_currentPosition, ios::beg);   
        objDownloader->mystream.write((char*)&objDownloader->_downloaded, sizeof(long long));

        long long  pos = objDownloader->mystream.tellp();           
        cout << "POS TEL: " << pos << endl;

        return size * nmemb;
    }
    else{

        if (objDownloader->mystream.is_open())
            objDownloader->mystream.close();            
        return -1;
    }

}

1 个答案:

答案 0 :(得分:3)

您的问题与fstream无关,但与处理内存无关。

以下代码将生成3GB的文件,没有任何问题,使用tellp()显示进度,并使用seekp()在文件末尾的位置:

cout << "size_t is limted to " << numeric_limits<size_t>::max() << " bytes (" << numeric_limits<size_t>::max() /1024/1024<<" MB)"<< endl;
cout << "streamsize is limited to " << numeric_limits<streamsize>::max() << " bytes (" << numeric_limits<streamsize>::max() / 1024 / 1024/1024/104 << " TB)" << endl;

static char mbloc[1024*1024]; 
fill_n(mbloc, sizeof(mbloc), 'A'); 
const size_t blocs = 3*1024; 
ofstream os("test.out"); 
for(int i = 0; i < blocs && os; i++) {
    os.write(mbloc, sizeof(mbloc));
    if(i % 512)
        cout << "tellp() -> " << os.tellp() << "\r";
}
cout << endl;
os.seekp(0, ios::end); 
cout << os.tellp() << " end"<<endl;  
os.close();
cout << "File generation finished"; 
事实上,fstreams被认为是非常大的。这就是ostream::write()使用streamsize类型计数的原因。

事实上,tellp()返回-1,因此发生了另一次失败。您可以通过检查fstream操作的状态来识别此故障的根源,以确定哪些成功以及哪些成功失败。

您的声明显示您尝试从内存缓冲区写入所有内容:

     objDownloader->mystream.write(static_cast<char*>(ptr), written);

很遗憾,在Windows下,您将遇到2GB that applies to a 32 bit process限制的问题。这可能会导致写入失败,不是因为fstream限制,而是因为底层操作系统的内存限制。

如果编译为64位并在64位进程上运行,如果计算机上有足够的内存,则可以将此限制扩展到8TB。但是如果你操纵这么大的数据,你最好用较小的块写在磁盘上,而不必将整个文件保存在内存中。