【问题标题】:Searching for structures in a continuous, unstructured file stream在连续的非结构化文件流中搜索结构
【发布时间】:2015-01-16 11:37:38
【问题描述】:

我正在尝试找出一种(希望是简单的)方法来读取大型的非结构化文件,而不会碰到缓冲区的边缘。这里有一个例子很有帮助。

假设您正在尝试对 16GB 闪存驱动器进行一些数据恢复,并将驱动器的转储保存到 16GB 文件中。您想扫描图像,寻找某些感兴趣的项目。如果文件更小,您可以将整个文件读入内存缓冲区(比如说 1MB),然后对缓冲区进行简单的扫描。但是,由于它太大而无法一次全部读取,因此您需要分块读取它。问题是感兴趣的项目可能无法完美对齐以落入单个 1MB 缓冲区内。换句话说,它可能最终跨越缓冲区的边缘,因此它在一次读取期间从缓冲区的末尾开始,并在下一次(甚至更远)结束。

在过去的某个时候,我通过使用两个缓冲区并将第二个缓冲区复制到第一个缓冲区以创建一种滑动窗口来处理这个问题,但是我想这应该是一个足够常见的场景,有更好的,现有的解决方案。我查看了内存映射文件,认为它们可以让您通过简单地增加数组索引/指针来读取文件,但由于地图视图大小的限制,我最终陷入了与以前完全相同的情况。我尝试寻找一些使用带有偏移量的MapViewOfFile 的实际示例,但我能找到的只是人为的示例,跳过了这些示例。

这种情况通常如何处理?

【问题讨论】:

    标签: c++ windows stream unmanaged


    【解决方案1】:

    如果您在 64 位环境中运行,我只会使用内存映射文件。进程没有(合理的)内存限制。你可以读入文件,甚至跳转,操作系统会在磁盘之间交换内存。

    以下是一些基本信息:

    http://msdn.microsoft.com/en-us/library/ms810613.aspx

    这里是文件查看器的示例:

    http://www.catch22.net/tuts/memory-techniques-part-1

    这种情况适用于 x64 中的 2.8GB 文件,但在 win32 中失败,因为它不能为每个进程分配超过 2GB 的空间。它非常快,因为它只涉及 pBuf 数组中的第一个和最后一个字节。修改方法以遍历缓冲区并计算“零”字节的数量按预期工作。您可以看到内存占用量随着它的增加而增加,但该内存只是虚拟分配的。

    #include "stdafx.h"
    #include <string>
    #include <Windows.h>
    
    TCHAR  szName[] = TEXT( pathToFile );
    
    int _tmain(int argc, _TCHAR* argv[])
    {
       HANDLE hMapFile;
       char* pBuf;
    
       HANDLE file = CreateFile( szName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
       if ( file == NULL )
       {
             _tprintf(TEXT("Could not open file object (%d).\n"),
                 GetLastError());
          return 1;
       }
    
       unsigned int length  = GetFileSize(file, 0);
    
       printf( "Length = %u\n", length );
    
    
       hMapFile = CreateFileMapping( file, 0, PAGE_READONLY, 0, 0, 0 );
    
       if (hMapFile == NULL)
       {
          _tprintf(TEXT("Could not create file mapping object (%d).\n"),  GetLastError());
          return 1;
       }
    
       pBuf = (char*) MapViewOfFile(hMapFile,  FILE_MAP_READ, 0,0, length);
    
       if (pBuf == NULL)
       {
          _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
    
           CloseHandle(hMapFile);
    
          return 1;
       }
    
       printf("First Byte: 0x%02x\n", pBuf[0] );
       printf("Last Byte: 0x%02x\n", pBuf[length-1] );
       UnmapViewOfFile(pBuf);
    
       CloseHandle(hMapFile);
    
       return 0;
    }
    

    【讨论】:

    • 就像我说的,我已经尝试过内存映射文件。问题是,即使是64位系统,地图的视图也是有限的,所以我不能映射一个大文件,必须不断改变视图的偏移量和重新调整指针,这和简单的没什么区别读入缓冲区。
    • 您可以同时映射文件的多个视图。您可以根据需要取消映射和重新映射视图以在文件数据中创建滑动窗口,或调整视图大小以使其更小/更大。如果您需要检查跨越两个视图的内容,您可以创建一个包含现有视图范围的新视图。当您找到感兴趣的内容时,您可以根据需要使用尽可能多的视图来浏览它,直到找到该项目的结尾。 “我发现了一些我可能感兴趣的东西,让我看看它的更大视图”。
    • 这是内存映射相对于传统缓冲文件 I/O 的优势。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 2011-03-10
    • 2014-01-04
    相关资源
    最近更新 更多