[WinXP] Чтение больших файлов. > 200 МБайт.

Тема в разделе "WASM.WIN32", создана пользователем MuForum, 5 май 2010.

  1. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Доброго времени суток.

    # Задача: Открыть файл размером от 200 МБайт до 2 Гигабайт, и извлечь из него строчки, которые включают в себя вхождения поисковой строки.
    - То есть, если я задам поиск вхождения "sys", то мне должно вернуть все строки которые содержат символы "sys".
    - После чего этот текст мне нужно будет вывести на экран.


    Сначала попробовал сделать через std::ifstream/string, но скорость просто ужасная.... (Файл в 50 Мбайт грузится минуту...)
    - Сейчас смотрю в сторону "MMF" (Memory Maped File)


    P.S. -> Существуют ли какие-то ещё способы решить задачу? (Интересует самый производительный)
     
  2. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    grep for windows?
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Memory Mapped Files будет наиболее производительным, имхо.
     
  4. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Выделить в памяти буфер размером = (длина подстроки * 2)-1. -1 можно убрать.
    Цыкл:
    Считываем в буфер из файла.
    cmpsb и подобное.
    Обработка сравнения.
    Цыкл.
     
  5. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Это с чего бы? Обработка ошибок страниц и Paging I/O не самые быстрые операции, а если учесть наличие в системе множества сторонних фильтров, которых именно такой I/O и интересует, то можно сказать, что подобный путь не самый простой уж точно. Я бы сделал тупо последовательное чтение, т.е. открытие файла с соответстующими флагами, плюс правильно выбрал бы размер буфера для чтения.
     
  6. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Вот это тру! Вообще выше всякой похвалы!
    А вам никто никогда не говорил что читать весь файл целиком не ПРАВОСЛАВНО?!
    открой файл CreateFileA() получишь хендл. и читай себе построчно его, и в каждой строке ищи вхождения, нащел -- вывел/запомнил
     
  7. Phyber

    Phyber New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    96
    x64
    Объясните же почему File mapping не подходит для оптимального решения данной задачи? в отличии от чтения файла блоками.

    ключевая фраза : "читай себе построчно его"
     
  8. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    интересно построчно это как?))
    Похоже это пустой спор пока кто-то не сделает 2 метода и не проверит быстродействие)
     
  9. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Спроецировать файл весом 2 Гб на адресное пространство 32-разрядной системы - не получится (либо /3GB надо включить) :)
    Так что универсальный метод был озвучен x64 - открыть файл на чтение и в цикле считывать в буфер часть файла и искать строки в этом буфере + доп-я обработка на стыках частей файла.
     
  10. assasincore

    assasincore New Member

    Публикаций:
    0
    Регистрация:
    7 апр 2010
    Сообщения:
    55
    Через .getline() ? ))


    x64 Прав.... читай буферами по несколько метров и точка...
     
  11. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Собственно сделал по началу так... (C++ Builder 2009)
    Код (Text):
    1. void _fastcall TFFMain::LoadDataFromFile(AnsiString sFilePath, AnsiString sSearchText, bool bMatchCase)
    2.  
    3. {
    4.  
    5.     if ( FileExists(sFilePath) == false )
    6.  
    7.     {
    8.  
    9.         return;
    10.  
    11.     }
    12.  
    13.     // ----
    14.  
    15.     std::ifstream in(sFilePath.c_str());
    16.  
    17.     // ----
    18.  
    19.     std::string line            = "";
    20.  
    21.     std::string line2           = "";
    22.  
    23.     // ----
    24.  
    25.     std::string szSearchText    = sSearchText.c_str();
    26.  
    27.     // ----
    28.  
    29.     if ( in.is_open() == true )
    30.  
    31.     {
    32.  
    33.         while ( in.eof() == false )
    34.  
    35.         {
    36.  
    37.             getline(in, line);
    38.  
    39.             // ----
    40.  
    41.             if ( line.find(szSearchText) == -1 )
    42.  
    43.             {
    44.  
    45.                 continue;
    46.  
    47.             }
    48.  
    49.             // ----
    50.  
    51.             m_log->Lines->Append(line.c_str());
    52.  
    53.  
    54.  
    55.         }
    56.  
    57.     }
    58.  
    59.     // ----
    60.  
    61.     in.close();
    62.  
    63. }
    - Но скорость обработки просто ужасна...

    - То есть, читаю допустим 5 метров, затем в цикле ищу конец строки и затем проверяю на вхождение?
     
  12. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    MuForum
    Сделай буфер создаваемым в рантайме, а в ком. строке укажи аргумент , который означает его длину. Так быстрее выявишь нужную и правильную длину буфера ;)
     
  13. Butters

    Butters New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    47
    Имхо читать постранично в пару выделенных или статических буфера, искать вхождение первого символа искомой строки, дальше сравнивать остальное и дополнительно обрабатывать конец - начало следующего буфера. На чистом Win API побыстрее будет.
     
  14. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    Butters А че MapViewOfFile уже не чистое ВинАПИ ? )
     
  15. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    MuForum
    Зачем вы заикливаетесь на понятие "конец строки" - поставьте задачу немного по-другому: найти в файле последовательность байт определенной длины. Все - написанный вами код будет универсальным и будет решать достаточно большой круг задач.
     
  16. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    #13
    Хватит и одного буфера len_substr_*2.
    После каждой итерации считывания не забываем корректировать указатель в файле:
    указатель = указатель + len_substr_*2 - ecx после cmps
     
  17. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Название темы вводит в заблуждение, под большими файлами в винде обычно имеют ввиду
    размер более 2^31–2 байт
     
  18. assasincore

    assasincore New Member

    Публикаций:
    0
    Регистрация:
    7 апр 2010
    Сообщения:
    55
    Это не имеет значение, для нормального алгоритма размер файл будет означать количество операций, а не возможность выполнения....

    Псевдо

    Что же происходит у вас?
    getline(in, line); //Вы уже будете проверять каждый байт, причем это самая медленная функция для чтения файла. Она кажется читает по несколько байт(случайно не один? во смеху будет... ).
    line.find(szSearchText) // Второй проход функции

    При том при всем что проход файл(а точнее сравнения байт) выполняется дважды, это не сильно отразится на производительности, а вот как читает getline(in, line) это полный ПИПЕЦ.... ))
     
  19. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    http://www.wasm.ru/forum/viewtopic.php?pid=222780#p222780
     
  20. Butters

    Butters New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    47
    EvilsInterrupt
    Зачем здесь мапинг, когда хватит обычного ReadFile.