Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Обработка текстовых файлов больших размеров (2 - 3 ГГб) [D7, WinXP]


Страницы:   1 2

bsframer ©   (2006-04-26 08:59:00) 

Здраствуйте, Уважаемые. Может вопрос и глупый, но мучаюсь уже второй день. Есть текстовый файл большого размера (2-3 ГГб), строки порядка 200 символов. Вопрос, как можно провести в нем сортировку по возрастанию (убыванию)? Пробовал ReadLn, BlockRead, TFileStream - медленно (нужно чтоб 50 МГб примерно за 5 минут пробегало). Через TStringList можно (100 МГб - 2,5 минуты), но в него влазит порядка 500 МГб (Оперативки 1 ГГб), дальше сообщение Out of Memory и стопор. Разрезание файла на куски думал, но это геморойно. Слышал про FileMapping, но не знаю как с ним работать и подойдет ли он вообще. Может есть какой способ, чтоб оперативки меньше жрало и работало быстрее, или я не так пробовал?


SYSCON   (2006-05-02 09:30:00) [1]

А виндовая Sort.exe для этой задачи не подойдет?


GrayFace   (2006-04-29 08:12:00) [2]

> Сергей М. ©   (28.04.06 11:16) [29]
> О какой разности смещений можно говорить для последней строки?

Ежу понятно, что для нее придется сделать исключение - хранить длину  или вычислить смещение, на котором бы находилась следующая строка. Наверное, лучше второе.


han_malign   (2006-04-28 11:47:00) [3]


> Слышал про FileMapping, но не знаю как с ним работать и  подойдет ли он вообще.

- File mapping поможет мало, все равно окно больше максимального доступного не фрагментированного диапазона виртальных адресов не сделаешь(MapViewOfFile), т.е. примерно такое же ограничение как StringList...
Но для общего развития:
type
  TFileMappingData = class
  private
     F_hFile: THandle;
     F_hMap: THandle;
     F_sFileName: string;
     F_pData: pointer;
     F_cbSize: integer;
     F_dwError: DWORD;
  public
     constructor Create(const aFileName: string= '');
     destructor Destroy; override;
     function Reset(const aFileName: string= ''): boolean;
     property Data: pointer read F_pData;
     property Size: integer read F_cbSize;
     property Error: DWORD read F_dwError;
  end;
implementation
constructor TFileMappingData.Create(const aFileName: string= '');
begin
  F_hFile:=INVALID_HANDLE_VALUE;
  Reset(aFileName);
end;

destructor TFileMappingData.Destroy;
begin
  Reset;
end;

function TFileMappingData.Reset(const aFileName: string= ''): boolean;
begin
  Result:=F_pData<>nil;
  if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(aFileName), Length(aFileName), PChar(F_sFileName), Length(F_sFileName))=2)
  then exit;
  if(F_pData <> nil)then UnmapViewOfFile(F_pData);
  if(F_hMap <> 0)then CloseHandle(F_hMap);
  if(F_hFile <> INVALID_HANDLE_VALUE)then CloseHandle(F_hFile);
  F_pData:=nil;
  F_hMap:=0;
  F_hFile:= INVALID_HANDLE_VALUE;
  Result:= true; F_dwError:= ERROR_NO_DATA;
  if(aFileName <> '')then begin
     F_hFile:= CreateFile(PChar(aFileName),GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
     if(F_hFile <> INVALID_HANDLE_VALUE)then begin
        F_hMap:= CreateFileMapping(F_hFile, nil, PAGE_READONLY, 0, 0, nil);
        if(F_hMap<>0)then begin
           F_pData:= MapViewOfFile(F_hMap, FILE_MAP_READ, 0, 0, 0);
           if(F_pData <> nil)then begin
              F_cbSize:= GetFileSize(F_hFile, nil);
              F_sFileName:= aFileName;
              F_dwError:= NO_ERROR;
              exit;
           end else F_dwError:=GetLastError;
           CloseHandle(F_hMap);
        end else F_dwError:=GetLastError;
        CloseHandle(F_hMap);
     end else F_dwError:=GetLastError;
     Result:=false;
  end else begin
     F_sFileName:='';
  end;
end;

- мапирует файл "целиком"(пытается), только для чтения...


Сергей М.   (2006-04-28 11:16:00) [4]


> GrayFace ©   (28.04.06 11:08) [28]


> хранить размер не нужно


> разность смещений


О какой разности смещений можно говорить для последнейстроки ?


GrayFace   (2006-04-28 11:08:00) [5]

> Да куда мне это запихать, вся информация будет чуть меньше
> размером чем сам файл.

Длина строк ~ 200 символов, размер файлов = 2-3 GB. Если хранить смещения и первые 4 символа, получаем 3000/200*8=120 MB. Максимальный размер обрабатываемого файла = 2/8*200=50GB. Думаю, достаточно. Конечно, при подобных размерах своп придется подергать.
А хранить размер не нужно. Он = разность смещений - размер перевода строки.
Быструю сортировку см. в TStringList.Sort.


bsframer   (2006-04-26 14:41:00) [6]

:) а пример кода можно?


Сергей М.   (2006-04-26 14:22:00) [7]

До 4Гб - тип DWORD.

Классы - на твой вкус.
Можешь вообще их не использовать.


bsframer   (2006-04-26 14:15:00) [8]


> читаешь последовательно строки исх.файла, фиксируешь их
> смещение и размер.
> Далее сортируешь полученную таблицу


Сортировка конечно,  можно подробнее описать (какие типы и классы использовать)?


Сергей М.   (2006-04-26 14:00:00) [9]


> bsframer   (26.04.06 13:50) [22]


Тебе сортировка нужна или "пихать" ?


bsframer   (2006-04-26 13:59:00) [10]

Брать последнюю строчку в Memo (она будет либо полной либо нет) взять ее длинну, удалить. Затем установить указатель в файле на 64 кб - Длинна последней строчки и считывать следующие 64 кб.


bsframer   (2006-04-26 13:50:00) [11]

Да куда мне это запихать, вся информация будет чуть меньше размером чем сам файл. И еще если я прочитаю потоком 64 кб, мне проще записать их в Memo, он автоматом строки разбивает, я думаю должно быстрее быть чем самому поиск осуществлять.


GrayFace   (2006-04-26 13:42:00) [12]

Сомневаюсь, что удастся сильно обгонать ReadLn. Кстати, вместе с позициями и длинами строк полезно будет хранить первые несколько символов.


Сергей М.   (2006-04-26 13:38:00) [13]

Подключить-то можно, но смысла в этом нет.
Без индексирования данных результат будет удручающим.


bsframer   (2006-04-26 13:33:00) [14]

А через ADO (Microsoft Text Driver) реально подключить и обработать такой файл?


Сергей М.   (2006-04-26 12:24:00) [15]


> значит всетаки побайтно брать?


Зачем побайтно ?

Считывай сразу по 64кб и ищи там символы-разделители, учитывая при этом результаты поиска конца последней строки при анализе предыдущих считанных 64кб


bsframer   (2006-04-26 11:52:00) [16]

Это понятно, значит всетаки побайтно брать? Другова способа нет?


Palladin   (2006-04-26 11:31:00) [17]

Общепринятый конец у строки там где есть #13 или #10 или #13#10


bsframer   (2006-04-26 11:16:00) [18]

Неподскажите чем реализовать быстрое считывание строк. TFileStream не знает где конец у строки, Readln медленный, побайтно тоже медленно.


Сергей М.   (2006-04-26 10:22:00) [19]

Если таки вариант с СУБД не устраивает никаким образом, построить самому индексную таблицу не так уж и сложно - читаешь последовательно строки исх.файла, фиксируешь их смещение и размер.
Далее сортируешь полученную таблицу (теперь обращение к строкам исх.файла - произвольное, а не последовательное) и уже имея ее отсортированную записываешь считываемые из исх.файла соотв.строки в результирующий файл.


Сергей М.   (2006-04-26 10:16:00) [20]


> bsframer   (26.04.06 09:52) [9]


Подойдет даже FB Embedded


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо