2

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

我四处寻找可以让我只缓冲文件的一部分的其他函数,但我没有找到任何文档专门说明缓冲区如何为这些函数工作(我对此有点新,所以也许我'我错过了明显的)。

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

你们对使用什么好的功能有任何意见吗?

4

4 回答 4

7

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

于 2009-08-19T18:56:10.040 回答
5

不确定 CreateFile 缓冲是什么意思 - CreateFile 不会读取文件的全部内容,此外,您需要先调用 CreateFile,然后才能调用 ReadFile。

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

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

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

于 2009-08-19T19:08:38.563 回答
5

调用CreateFile()本身不会缓冲或读取目标文件的内容。在调用 CreateFile() 之后,您必须调用ReadFile()来获取您想要的文件的任何部分,例如读取文件的第一个 KB:

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( ),例如从 1 兆字节开始读取 1 KB 到文件中:

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() 读取的最后一个字节之后的字节。

此外,您应该阅读您使用的文件管理函数的文档,并适当地检查返回值以捕获可能发生的任何错误。

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

于 2009-08-19T19:20:09.400 回答
1

我相信你想要MapViewOfFile

于 2009-08-19T18:58:02.737 回答