如何将一个大的二进制文件写入磁盘
How to write a large binary file to a disk
我正在编写一个程序,它需要将一个大的二进制文件(大约12 GiB或更多)写入磁盘。我已经创建了一个小的测试程序来测试这个功能。虽然为缓冲区分配RAM内存不是问题,但我的程序没有将数据写入文件。该文件仍然为空。
//size_t bufferSize=1000; //ok
//size_t bufferSize=100000000; //ok
size_t bufferSize=500000000; //fails although it is under 4GiB, which shouldn't cause problem anyways
double mem=double(bufferSize)*double(sizeof(double))/std::pow(1024.,3.);
cout<<"Total memory used: "<<mem<<" GiB"<<endl;
double *buffer=new double[bufferSize];
/* //enable if you want to fill the buffer with random data
printf("r[%i %]",0);
for (size_t i=0;i<(size_t)bufferSize;i++)
{
if ((i+1)%100==0) printf("r[%i %]",(size_t)(100.*double(i+1)/bufferSize));
buffer[i]=rand() % 100;
}
*/
cout<<endl;
std::ofstream outfile ("largeStuff.bin",std::ofstream::binary);
outfile.write ((char*)buffer,((size_t)(bufferSize*double(sizeof(double)))));
outfile.close();
delete[] buffer;
我实际上编译并运行了代码,就像你粘贴在那里一样,它工作了。创建一个4GB的文件
如果您使用的是FAT32文件系统,则最大文件大小为4GB。
否则我建议您检查:
- 可用磁盘空间的大小。
- 您的用户帐户是否有磁盘使用限制。
- 您拥有的可用RAM数量。
- 是否有运行时错误。
- @enhzflep关于打印数量的建议(尽管这是注释掉)
您似乎希望在写入文件之前有一个包含整个文件内容的缓冲区。
你做错了,通过:虚拟内存需求本质上是他们需要的两倍。您的进程保留缓冲区,但是当您将该缓冲区写入磁盘时,它会在操作系统的缓冲区中重复。现在,大多数操作系统会注意到您是顺序写入的,并且可能会很快丢弃它们的缓冲区,但是:这仍然是相当浪费的。
相反,您应该创建一个空文件,将其增长到所需的大小,然后将其视图映射到内存中,并在内存中对文件视图进行修改。对于32位主机,文件大小限制为1GB。对于64位主机,它仅受文件系统的限制。在现代硬件上,如果您有足够的可用RAM,那么以这种方式创建和填充1GB的文件只需1秒(!)。
多亏了RAII的神奇之处,您不需要做任何特别的事情来释放映射的内存,或者关闭/完成文件。通过利用boost,您还可以避免编写特定于平台的代码。
// https://github.com/KubaO/stackoverflown/tree/master/questions/mmap-boost-40308164
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/filesystem.hpp>
#include <cassert>
#include <cstdint>
#include <fstream>
namespace bip = boost::interprocess;
void fill(const char * fileName, size_t size) {
using element_type = uint64_t;
assert(size % sizeof(element_type) == 0);
std::ofstream().open(fileName); // create an empty file
boost::filesystem::resize_file(fileName, size);
auto mapping = bip::file_mapping{fileName, bip::read_write};
auto mapped_rgn = bip::mapped_region{mapping, bip::read_write};
const auto mmaped_data = static_cast<element_type*>(mapped_rgn.get_address());
const auto mmap_bytes = mapped_rgn.get_size();
const auto mmap_size = mmap_bytes / sizeof(*mmaped_data);
assert(mmap_bytes == size);
element_type n = 0;
for (auto p = mmaped_data; p < mmaped_data+mmap_size; ++p)
*p = n++;
}
int main() {
const uint64_t G = 1024ULL*1024ULL*1024ULL;
fill("tmp.bin", 1*G);
}
相关文章:
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- C++中读/写二进制文件
- 如何忽略某些二进制文件的执行?
- 以RAW形式恢复磁盘内容并转储为一个大二进制文件的应用程序
- 如何将一个大的二进制文件写入磁盘