2012-01-24 5 views
0

Быстрое предисловие. Мне очень удобно в .Net, но у меня ограниченный опыт работы на C++, поэтому я не уверен, что я делаю это хорошо. Я использую объект сопоставления файлов, чтобы получить то, что потенциально может быть относительно длинной строкой, состоящей из нескольких тысяч имен файлов. Эта функция может быть вызвана с помощью ImageOverlayHandler, подключенного к проводнику Windows, так что потребление скорости и памяти вызывает беспокойство. Этот код потенциально может быть вызван сотнями запросов оверлей одновременно (но только в случаях краев). В приведенном ниже коде это эффективный способ сделать это? Используя этот подход, если я правильно понял свой код, я не буду создавать локальную копию сопоставленного файла, а boost :: contains call должен быть довольно быстрым. Любые мысли о том, как я могу это улучшить, или как я должен делать это по-другому? в предыдущей итерации я использовал векторы и т. д., но похоже, что она будет использовать гораздо больше памяти.Поиск большой строки C++ из сопоставления файлов быстро и эффективно

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); 
} 
+0

Что вы на самом деле пытаетесь сделать? Вы действительно просто проверяете, содержит ли ваша огромная строка «C: \ FOLDER1»? Если да, не было бы легче проверить это в другом коде и просто передать bool на код C++? – arx

+0

Поскольку вы не определяете BUF_SIZE в своем коде, неясно, будет ли это работать. Он может работать во время тестирования и сбой, если ваша строка поиска находится за пределами конца буфера. Также создание 'wstring' делает копию, удваивая ваши требования к памяти. –

+0

А, так это создание дубликата? Это не идеально. Могу ли я просто передать метод повышения LPCWSTR, чтобы избежать этого? Размер buf установлен в 0, который должен отображать весь файл вправо? –

ответ

1

Если вы создаете список имен файлов один раз или только изредка и неоднократно тестируете его, вы можете воспользоваться бинарным поиском. Бинарный поиск требует двух вещей: список ввода должен быть отсортирован, и вы должны иметь возможность индексировать любой элемент списка эффективно.

Вы можете выполнить первое требование, отсортировав список на C#, прежде чем записывать его в файл. Вы можете выполнить второе требование, создав список целых чисел, которые представляют смещение в строке для начала каждого имени файла. Поскольку каждое целое число одного размера, оно может быть проиндексировано, и одно простое обращение к фактическому имени файла.

Алгоритм std::equal_range выполнит двоичный поиск. Если возвращенные итераторы равны, элемент не найден, иначе первый итератор указывает на него.

Чтобы выполнить косвенную привязку к строке, вам понадобится пользовательская функция компаратора, чтобы перейти к equal_range.

+0

Хорошо, это имеет смысл. Поэтому я бы просто использовал эти два вместе, чтобы выполнить двоичный поиск строки с именами файлов правильно? –

+0

@tghamm, справа. И в случае, если это неясно, вам нужно создать список целых чисел в файле, иначе вы можете также выполнить линейный поиск, потому что это будет работать так же, как поиск начала каждого имени файла. –

+0

Спасибо за совет. В итоге я быстро перевернул собственный бинарный поиск, кажется, намного быстрее. –

1

Поскольку вы охарактеризовали эти данные в виде списка имен файлов, рассмотреть вопрос о создании каждого файла в std::set или std::unordered_set (C++ 11) или boost::unordered_set (C++ 03 и выше).

Ваш подход имеет O (n) эффективность.

std::set будет O (log n) эффективность.

unordered_set был бы O (1) эффективность.

Примечание: создание любого из этих контейнеров должно выполняться один раз, заранее. Не для каждого звонка GetFolders()

+0

Эй, Дрю, это интересно. Итак, вот немного уловки, и, возможно, это лучше всего подходит для другого вопроса (я здесь новый).Этот список файлов создается на C#, а затем сортируется в сопоставлении файлов, поэтому я не уверен, как я собираюсь заполнить упорядоченный набор, который нужно нажать. –

+0

@tghamm: Я предлагаю задать этот вопрос как новый, конкретный вопрос. Тогда вы получите больше очков. –

+0

Хорошо, сделаем, спасибо за информацию! –

Смежные вопросы