读取二进制文件而不用C ++将整个文件缓冲到内存中

时间:2009-08-19 18:52:25

标签: c++ winapi memory-management file-io buffer

为了制作二进制比较器,我试图使用CreateFileW函数读取两个文件的二进制内容。但是,这会导致整个文件被缓冲到内存中,这对于大型(500MB)文件来说就成了问题。

我已经四处查找了其他函数,这些函数只会缓冲部分文件,但我没有找到任何专门说明缓冲区如何为这些函数工作的文档(我在这方面有点新)所以也许我错过了明显的事情。

到目前为止,我似乎找到的最佳匹配是ReadFile。它似乎有一个可定义的缓冲区,但我不完全确定在幕后不会有另外的缓冲区,就像CreateFileW一样。

你们对于什么是好的功能有什么意见?

4 个答案:

答案 0 :(得分:7)

您可以使用内存映射文件来执行此操作。使用createFile打开,使用createFileMapping然后MapViewOfFile获取指向数据的指针。

答案 1 :(得分:5)

不确定CreateFile缓冲的含义 - CreateFile不会读取文件的全部内容,此外,您需要先调用CreateFile才能调用ReadFile。

ReadFile会做你想做的事情 - 操作系统可以在数据之前做一些读取机会性地缓存数据,但它不会读取整个500 MB的文件。

如果您确实不想进行缓冲,请将FILE_FLAG_NO_BUFFERING传递给CreateFile,并确保您的文件访问是卷扇区大小的倍数。我强烈建议你不要这样做 - 系统文件缓存存在是有原因的并且有助于提高性能。在内存中缓存文件应该不会影响整个系统的内存使用情况 - 在内存压力下,系统文件缓存会缩小。

正如其他人所提到的,您也可以使用内存映射文件。内存映射文件和ReadFile之间的区别主要只是接口 - 最终文件管理器将以类似的方式满足请求,包括一些缓冲。界面看起来更直观一些,但请注意,发生的任何错误都会导致异常,需要捕获,否则会导致程序崩溃。

答案 2 :(得分:5)

调用CreateFile()本身不会缓冲或以其他方式读取目标文件的内容。调用CreateFile()之后,必须调用ReadFile()来获取所需文件的任何部分,例如读取文件的第一个千字节:

DWORD cbRead;
BYTE buffer[1024];
HANDLE hFile = ::CreateFile(filename,
                            GENERIC_READ,
                            FILE_SHARE_READ,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
::ReadFile(hFile, sizeof(buffer), &cbRead, NULL);
::CloseHandle(hFile);

此外,如果要读取文件的随机部分,可以在调用ReadFile()之前使用SetFilePointer(),例如读取一千兆字节,从文件开始读取一兆字节:

DWORD cbRead;
BYTE buffer[1024];
HANDLE hFile = ::CreateFile(filename,
                            GENERIC_READ,
                            FILE_SHARE_READ,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
::SetFilePointer(hFile, 1024 * 1024, NULL, FILE_BEGIN);
::ReadFile(hFile, sizeof(buffer), &cbRead, NULL);
::CloseHandle(hFile);

当然,您可以在文件打开时多次调用SetFilePointer()和ReadFile()。对ReadFile()的调用隐式地将文件指针设置为紧跟ReadFile()读取的最后一个字节之后的字节。

此外,您应阅读所使用的File Management Functions的文档,并相应地检查返回值以捕获可能发生的任何错误。

Windows可以自行决定使用可用的系统内存来缓存打开文件的内容,但如果正在运行的程序需要内存,则该进程缓存的数据将被丢弃(毕竟,缓存的数据可能只是如果需要,请从磁盘重新读取。)

答案 3 :(得分:1)

我相信你想要MapViewOfFile

相关问题