快速有效地从文件映射中搜索大型c ++字符串

时间:2012-01-24 15:52:21

标签: c++ boost

快速序言,我对.Net感到非常满意,但对c ++的经验有限,所以我不确定我是否做得很好。 我正在使用文件映射对象来检索可能是一个相对较长的字符串,由多达数千个文件名组成。可以从连接到Windows资源管理器的ImageOverlayHandler调用此函数,因此速度和内存消耗都很重要。这个代码可能会被一次数百个覆盖请求调用(但仅限于边缘情况)。在下面的代码中,这是一种有效的方法吗?使用这种方法,如果我已正确理解我的代码,我将不会制作映射文件的本地副本,并且boost :: contains调用应该非常快。关于我如何改进它,或者我应该如何做到这一点的任何想法?在之前的迭代中我使用了矢量等,但这似乎会使用更多的内存。

HRESULT GetFolders()
{
    HANDLE hMapFile;
    LPCWSTR pBuf;
    hMapFile = OpenFileMapping(
               FILE_MAP_ALL_ACCESS,   // read/write access
               FALSE,                 // do not inherit the name
               szFolderName);               // name of mapping object

    if (hMapFile == NULL)
    {
       return NULL;
    }
    pBuf = (LPCWSTR) MapViewOfFile(hMapFile, // handle to map object
           FILE_MAP_ALL_ACCESS,  // read/write permission
           0,
           0,
           BUF_SIZE);

    if (pBuf == NULL)
    {
       CloseHandle(hMapFile);

       return NULL;
    }

    wstring resOut = (wstring)pBuf;

    bool val = boost::contains(resOut, L"C:\\FOLDER1");
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
}

2 个答案:

答案 0 :(得分:1)

由于您将此数据描述为文件名列表,因此请考虑将每个文件名放在std::setstd::unordered_set(C ++ 11)或boost::unordered_set(C ++ 03及更高版本)中)。

您的方法具有 O(n)效率。

std::set将具有 O(log n)效率。

unordered_set会有 O(1)效率。

注意:任何这些容器的创建都应该提前完成一次。不适用于GetFolders()

的每次通话

答案 1 :(得分:1)

如果您正在创建一次或仅偶尔创建文件名列表并重复测试,您可以从二进制搜索中受益。二进制搜索需要两件事:输入列表必须排序,并且您必须能够有效地索引到列表的任何元素。

在将文件写入文件之前,您可以通过在C#中对列表进行排序来满足第一个要求。您可以通过创建一个整数列表来满足第二个要求,这些整数表示每个文件名开头的字符串偏移量。由于每个整数的大小都相同,因此可以将其编入索引,并且只需一个简单的间接即可获得实际的文件名。

std::equal_range算法将执行二进制搜索。如果返回的迭代器相等,则找不到该项,否则第一个迭代器指向它。

您需要一个自定义比较器函数传递给equal_range来对字符串进行间接处理。