如果我有一个巨大的文件(例如1TB,或任何不适合RAM的大小.文件存储在磁盘上).它由空间划分.我的RAM只有8GB.我可以在ifstream中读取该文件吗?如果没有,如何读取文件块(例如4GB)?
zne*_*eak 14
你可以做几件事.
首先,打开一个大于你拥有的RAM量的文件是没有问题的.你将不能够做的就是复制整个文件活到你的记忆.最好的办法是找到一种方法,一次只读几个块并处理它们.您可以将其ifstream用于此目的(ifstream.read例如).分配一个兆字节的内存,读取该文件的第一兆字节,冲洗并重复:
ifstream bigFile("mybigfile.dat");
constexpr size_t bufferSize = 1024 * 1024;
unique_ptr<char[]> buffer(new char[bufferSize]);
while (bigFile)
{
bigFile.read(buffer.get(), bufferSize);
// process data in buffer
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是将文件映射到内存.大多数操作系统都允许您将文件映射到内存,即使它大于您拥有的物理内存量.这是因为操作系统知道与文件关联的每个内存页面都可以按需映射和取消映射:当您的程序需要特定页面时,操作系统会将其从文件中读取到您的进程内存中并交换出一个页面暂时没有使用过.
但是,这仅在文件小于理论上可以使用的进程的最大内存量时才有效.这不是64位进程中1TB文件的问题,但它不适用于32位进程.
还要注意你召唤的精神.内存映射文件与从中读取文件不同.如果文件突然从另一个程序中截断,您的程序可能会崩溃.如果修改数据,如果无法保存回磁盘,则可能会耗尽内存.此外,您的操作系统用于分页进出内存的算法可能不会以显着优势的方式运行.由于这些不确定性,我会考虑映射文件只有在使用第一个解决方案的块中读取它时才能工作.
在Linux/OS X上,您可以使用mmap它.在Windows中,你会打开一个文件,然后使用CreateFileMapping然后MapViewOfFile.
我相信您不必将所有文件都保存在内存中。通常,人们希望按块读取和处理文件。如果你想使用ifstream,你可以这样做:
ifstream is("/path/to/file");
char buf[4096];
do {
is.read(buf, sizeof(buf));
process_chunk(buf, is.gcount());
} while(is);
Run Code Online (Sandbox Code Playgroud)