【问题标题】:File Mapping,How to open a file(txt) from a specific location文件映射,如何从特定位置打开文件(txt)
【发布时间】:2021-06-09 08:51:53
【问题描述】:

我有一个很大的 .txt 文件(超过 1GB)。在寻找快速打开它的方法时,我发现了映射。

我设法使用CreateFile(),然后我创建了一个char buffer[],最后将文件内容与ReadFile() 一起放入缓冲区。问题是文件太大,所以我不能一次将它全部加载到缓冲区中,因为我无法制作那么大的数组。

我认为解决方案是在.txt 文件中的指定位置打开和关闭文件,每次都获取一些文件内容。我发现解释映射的唯一来源是on MSDN,但我不知道该怎么做。

那么最后,如何读取带有映射的大文件呢?

HANDLE my_File = CreateFileA("words.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
if (my_File == INVALID_HANDLE_VALUE)
{
    cout << "Failed to open file" << endl;
    return 0;
}
    
constexpr size_t BUFFSIZE = 1000000;
    
char buffer[BUFFSIZE];
DWORD dwBytesToRead = BUFFSIZE - 1;
DWORD dwBytesRead = 0;
    
BOOL my_Bool = ReadFile(my_File,(void*)buffer, dwBytesToRead, &dwBytesRead, NULL);
    
if (dwBytesRead > 0)
{
    buffer[dwBytesRead] = '\0';
    cout << "FILE IS: " << buffer << endl;
}
    
CloseHandle(my_File);

【问题讨论】:

  • 问题是文件太大,所以我无法一次将它全部加载到缓冲区中,因为我无法制作那么大的数组。 b> 我假设出于某种原因您正在创建一个 32 位应用程序。
  • 您需要整个文件吗?通常,您可以读取和处理一个数据块,然后将下一个块读入您用于第一个块的同一存储空间,处理它,然后重复直到到达文件末尾。
  • 我该怎么做?
  • 通常,提出此类问题的更好方法是展示您认为您在该问题中的最佳尝试。这为回答者提供了一个更好的答案起点。也许您误解了一个小细节,并且可以快速得到答案。也许尝试偏离了正确的道路并找到了通往纳尼亚的路,但回答者可以告诉您您迷路的地方并朝正确的方向轻推。如果您什么都不显示,则不知道从哪里开始或从哪里停下来,最终得到的答案涵盖的范围太广,以至于您一次坐下来就无法理解。
  • 注意:Windows 系统的默认堆栈大小通常为 1 兆字节。 char buffer[BUFFSIZE]; 大约 1 兆字节,使程序危险地接近堆栈溢出并且本身就不稳定。如果您动态分配缓冲区或将其设为static 使其不在堆栈上,您将不会那么容易遭受堆栈溢出并且可以获得更大的缓冲区。可能要大几个数量级。

标签: c++ winapi mapping readfile createfile


【解决方案1】:

我认为你很困惑。将文件的部分或全部映射到内存中的全部目的是避免需要自己缓冲数据。相反,操作系统会为您处理这些,允许您通过指针访问文件的内容,就像您访问任何其他内存数据结构一样。

只有您可以决定这是否是最适合您的解决方案。在 32 位应用程序中,1GB 是一个很大的寻址空间。在 64 位应用程序中没有这样的问题。正如 cmets 中所提到的,将文件分块读取到较小的缓冲区中可能是更好的选择,特别是如果您想按顺序处理它。


有关如何内存映射文件的一些示例代码,请参阅:

How to CreateFileMapping in C++?

【讨论】:

  • 我使用 fstream 打开并读取 txt 文件到一个数组中,使用一个小的 txt 它工作得很好,但是对于大的它永远不会结束,我找到的唯一解决方案是映射,但我知道如何做吧
  • 在我的回答中添加了一些内容。
  • 我在搜索时也发现了该帖子,但我仍然无法为文件分配足够的内存
  • @Jesepy "但对于大的它永远不会结束" - 那么你可能使用错了,但我们看不到你尝试了什么。
  • @PaulSanders "你应该将你的应用程序构建为 64 位" - 如果可能的话,最好是这样。但是没有什么可以阻止 32 位应用程序使用文件映射读取 GB 大小的文件。我曾经写过一个 32 位的日志查看器,它使用文件映射来查看 GB 大小的日志文件,它运行良好。只是不要一次映射整个文件的视图,以较小的块查看它,并根据需要移动视图。
猜你喜欢
  • 2017-07-17
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-05-03
  • 2014-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多