Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.10.31;
Скачать: [xml.tar.bz2];

Вниз

Текстовый файл огромного размера   Найти похожие ветки 

 
ИМХО ©   (2004-10-16 20:39) [0]

Гсопода, как работать с текстовым файлом огромного размера (>300 MB)? Понятно, что не при помощи TStringList.


 
begin...end ©   (2004-10-16 20:41) [1]

Наверное, это зависит от того, что ты с ним собираешься делать.


 
ИМХО ©   (2004-10-16 20:55) [2]

этот огромный файл - Unix mailbox (MBX)
нужно выцепить из него сообщения


 
jack128 ©   (2004-10-16 21:10) [3]

ИМХО ©   (16.10.04 20:55) [2]
Загружаешь в память, ну например, по 10 МБ файла - парсеришь на строки и ищешь, что те там надо. не нашел - грузишь следующие 10 МБ и так до победного конца.. Может можно как нить оптимизировать этот процесс, но нужны подробности.. формат этого файла..


 
ИМХО ©   (2004-10-17 07:58) [4]

еще идеи будут?


 
Alx2 ©   (2004-10-17 08:16) [5]

>ИМХО ©   (17.10.04 07:58) [4]

MMF - и все заботы на кэширование и оптимизацию доступа возьмет на себя операционка.


 
default ©   (2004-10-17 08:16) [6]

[3] по-моему всё сказано
хочешь больше сам давай больше


 
default ©   (2004-10-17 08:17) [7]

только хотел про MFF сказать
это только если доступ последовательный
а так быстрей самому подгружать как надо


 
ИМХО ©   (2004-10-17 11:06) [8]

что за MMF (или MFF)?

где можно об этом почитать? (с примерами)


 
VMcL ©   (2004-10-17 11:53) [9]

>>ИМХО ©  (17.10.04 11:06) [8]

MMF - Memory Mapped File.
Почитать можно в Windows SDK, MSDN.
См. CreateFileMapping(), MapViewOfFile(), UnmapViewOfFile().


 
ИМХО ©   (2004-10-17 12:14) [10]

есть внятные примеры?


 
Anatoly Podgoretsky ©   (2004-10-17 12:17) [11]

ИМХО ©   (16.10.04 20:39)  
Ну это же не огромный размер, а вполне обычный для логов, нормально считывается как в string так и в TStrings.
Я постоянно обрабатываю логи гораздо большего объема, с помощью обычного ReadLn, в зависимости от версии Дельфи надо учитывать разделители строк.


 
ИМХО ©   (2004-10-17 12:20) [12]

Толян, дык памяти никакой не хватит на гиговый текстовый файл!


 
Anatoly Podgoretsky ©   (2004-10-17 12:24) [13]

Это с ReadLn то, посмотри размер строк в ящиук, ты врядли увидишь свыше 80 байт, в крайнем случае несколько килобайт.
Другое дело если у тебя Д5-


 
Verg ©   (2004-10-17 12:36) [14]

Что-нибудь тапа этого

type
 TMemFile = record
    HFile, HMap : THandle;
    Size : DWORD;
    BaseAddress : pointer;
 end;

procedure AllocMemFile(const F : string;var MemFile : TMemFile);
begin
 FillChar(MemFile, sizeof(MemFile),0);
 with MemFile do
 begin
   HFile:=CreateFile(pchar(F), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0,0);
   if HFile<>INVALID_HANDLE_VALUE then
   begin
     Size:=GetFileSize(HFile, nil);
     HMap:=CreateFileMapping(HFile, nil, PAGE_READONLY,0,0,nil);
     if (HMap<>0) and (Size<>$FFFFFFFF) then
     begin
       BaseAddress:=MapViewOfFile(HMap,FILE_MAP_READ,0,0,0);
       if BaseAddress=nil then
       begin
         CloseHandle(HMap);
         CloseHandle(HFile);
         HFile:=INVALID_HANDLE_VALUE;
         HMap:=0;
       end;
     end else
     begin
       CloseHandle(HFile);
       HFile:=INVALID_HANDLE_VALUE;
     end;
   end;
 end;
end;

procedure FreeMemFile(var MemFile : TMemFile);
begin
 with MemFile do
 if (HFile<>INVALID_HANDLE_VALUE) and (BaseAddress<>nil) and (HMap<>0) then
 begin
   UnmapViewOfFile(BaseAddress);
   CloseHandle(HMap);
   CloseHandle(HFile);
   FillChar(MemFile, sizeof(MemFile),0);
   HFile:=INVALID_HANDLE_VALUE;
 end;
end;


 
ИМХО ©   (2004-10-17 13:14) [15]


> Anatoly Podgoretsky ©   (17.10.04 12:24) [13]
> Это с ReadLn то, посмотри размер строк в ящиук, ты врядли
> увидишь свыше 80 байт, в крайнем случае несколько килобайт.
> Другое дело если у тебя Д5-


Да, у меня Delphi 5. Как это меняет дело?


 
ИМХО ©   (2004-10-17 14:43) [16]

Еще такой вопрос по сабжу.
Вот у меня на компе 158 MB оперативки.
Это какого объема текстовый файл можно загрузить в TStringList?


 
Sergey_Masloff   (2004-10-17 14:55) [17]

ИМХО ©   (17.10.04 14:43) [16]
>Еще такой вопрос по сабжу.
>Вот у меня на компе 158 MB оперативки.
Порядка 2 ГБ. Даже если оперативки 32 Мб. Или 16...


 
VMcL ©   (2004-10-17 15:00) [18]

>>Sergey_Masloff  (17.10.04 14:55) [17]

>Порядка 2 ГБ. Даже если оперативки 32 Мб. Или 16...

Ну, наверное, не совсем так. Зависит от размера файла подкачки.

>>ИМХО ©  (17.10.04 14:43) [16]

См. [3]. Только лучше использовать буфер не фиксированного размера, а размером с какую-то часть от общего объема ОЗУ, например, 25% (можно вообще в программе настройку соответствующую сделать).


 
ИМХО ©   (2004-10-17 15:28) [19]


> Sergey_Masloff   (17.10.04 14:55) [17]
> Порядка 2 ГБ. Даже если оперативки 32 Мб. Или 16...


Изволите шутить, товарищ Маслофф? А как насчет Out of Memory?


 
panov ©   (2004-10-17 15:28) [20]

Зачем тебе в память закачивать весь файл или куски?
Чем тебя ReadLn не устраивает?
Приведи хотя бы одну причину, почему тебя советы использовать последовательную обработку файла не устраивают. Иначе остальное - пустая болтовня.


 
ИМХО ©   (2004-10-17 15:30) [21]

да, все правильно, меня ReadLn устроило. При первом открытии я узнал начальные позиции сообщений. Но как затем организовать быстрый доступ по индексу?


 
ИМХО ©   (2004-10-17 15:32) [22]

Seek не работает с текстовыми файлами!!!


 
panov ©   (2004-10-17 15:33) [23]

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

Вывод очевиден - данные нужно закачивать в БД.

Второй вариант - писать свою систему управления БД, заточенную именно на эти данные.


 
panov ©   (2004-10-17 15:34) [24]

>ИМХО ©   (17.10.04 15:30) [21]

Но как затем организовать быстрый доступ по индексу?

А индекс где будешь хранить?


 
panov ©   (2004-10-17 15:35) [25]

Кстати, 300Мб - не очень большой объем логов.
У меня обрабатываются журналы размером около 2Гб.


 
ИМХО ©   (2004-10-17 15:36) [26]

сорри, СУБД отпадает. Решение должно быть проще.

Как теперь вытащить из текстового файла строки, скажем, с 2111570 по 2111710?


 
ИМХО ©   (2004-10-17 15:38) [27]

300 метров - это самое малое, что есть.


 
VMcL ©   (2004-10-17 15:39) [28]

>>ИМХО ©  (17.10.04 15:36) [26]

Строки фиксированной длины?


 
panov ©   (2004-10-17 15:40) [29]

>ИМХО ©   (17.10.04 15:36) [26]

В таком случае работа с файлом, как с текстовым, не подходит.

Существует такой выход:

1. Проход по файлу как по текстовому с вычислением смещений начала и конца каждой строки относительно начала файла.
2. Формирование дополнительного файла с индексами(по существу, это и будет своеобразный индексный файл).
3. Далее работаем с файлом как с файлом произвольного доступа.
  Любую строку теперь можно получить по ее индексу, вычисляя смещение относительно начала файла.


 
ИМХО ©   (2004-10-17 16:01) [30]


> VMcL ©   (17.10.04 15:39) [28]
> >>ИМХО ©  (17.10.04 15:36) [26]
>
> Строки фиксированной длины?


к сожалению, нет :(


 
ИМХО ©   (2004-10-17 16:02) [31]


> panov ©   (17.10.04 15:40) [29]
> В таком случае работа с файлом, как с текстовым, не подходит.
>
> Существует такой выход:


черт меня подери, а ведь это ИДЕЯ! Сенкс!


 
ИМХО ©   (2004-10-17 16:29) [32]

что-то я тут тормознулся...

как осуществить это:

> Проход по файлу как по текстовому с вычислением смещений
> начала и конца каждой строки относительно начала файла.

?

я думал, что это просто (считывай Readln(F, S) и складывай Length(S)), а это не так


 
Sergey_Masloff   (2004-10-17 16:59) [33]

ИМХО ©   (17.10.04 15:28) [19]
>Изволите шутить, товарищ Маслофф? А как насчет Out of Memory?
Тамбовский волк... ;-)
Что там с оут оф мемори? Родственник ваш оут оф мемори? Дядя он Вам?
 До ~2 Гб в TStringList влезет при любом объеме оперативки достаточном для работе ОС. Естественно ОС будет расширять файл подкачки и если его макс. размер ограничен то нехватка памяти случится раньше.
 Сейчас за 2 минуты написал тестовый пример и спокойно поместил в стринглист 1.7 Гб файл. Всего памяти в системе 256 Мб файл подкачки до примера 360 Мб после 1940 Мб.


 
Palladin ©   (2004-10-17 17:03) [34]

позвольте с вами категорично не согласится
естественно ОС не будет расширять его если он зафиксирован, как например сделано у меня для предотвращения его фрагментации


 
Sergey_Masloff   (2004-10-17 17:07) [35]

А чего не соглашаться. Если зафиксирован то естественно - у меня так и написано.
 Ваши личные настройки на общие принципы ну никак не влияют ;-) Кстати все равно все это баловство. В реальной работе абсолютно не заметно влияние фрагментации этой ;-)


 
Anatoly Podgoretsky ©   (2004-10-17 17:14) [36]

ИМХО ©   (17.10.04 13:14) [15]
Сушественно меняет, для Д5 это будет одна строка, поскольку он ен обрабатывает ограничители в формате Юник, Д6 и выше это делает. Значит тебе придется читать блоками и самому разбивать на строки и элементы. Жругой вариант перейти на Д6+
Тогда обработка будет выглядеть весьма просто и занимать минимум ресурсов.

while not Eof(F) do begin
  ReadLn(F, {f1, f2, ...} S);
  ...
end;


 
Palladin ©   (2004-10-17 17:20) [37]


> [35] Sergey_Masloff   (17.10.04 17:07)

точно... не заметил оговорки :)

а по поводу фрагметации... это не заметно на NTFS... но в win9x очень заметно... лучше сразу ограничить оптимизировать NU и тада будет счасте... иначе жуткое обращение к диску обеспечено... он расширит, а сузить забудет :)


 
Sergey_Masloff   (2004-10-17 17:24) [38]

Palladin ©   (17.10.04 17:20) [37]
>но в win9x очень заметно...
Понятно. Я и не знал.


 
panov ©   (2004-10-17 17:32) [39]

>ИМХО ©   (17.10.04 16:29) [32]

думал, что это просто (считывай Readln(F, S) и складывай Length(S)), а это не так

Ну, возможно, надо прибавить к длине каждой строки 2 (если строки заканчиваются #13#10)


 
ИМХО ©   (2004-10-17 18:22) [40]


> panov ©   (17.10.04 17:32) [39]
> Ну, возможно, надо прибавить к длине каждой строки 2 (если
> строки заканчиваются #13#10)


и здесь вы оказались абсолютно правы, спасибо.

а вот такой вопрос можно?

как теперь лучше обращаться к файлу:
1) через TFileStream.Create, затем Position и Read
или
2) через AssignFile, Reset(FromF, 1), Seek и BlockRead

???


 
default ©   (2004-10-17 18:38) [41]

ИМХО ©   (17.10.04 18:22) [40]
глянул я в окно CPU при вызове Reset вообщем там апишная OpenFile вызывается в конце концов так что это оболочка api ф-ий и всё поэтому по большому счёту разница, наверно, невелика что использовать, что удобней  то и используй


 
VMcL ©   (2004-10-17 18:41) [42]

>>ИМХО ©  (17.10.04 18:22) [40]

>как теперь лучше обращаться к файлу

Не важно. При последовательной обработке файла можно еще попробовать CreateFile() с флагом FILE_FLAG_NO_BUFFERING.


 
Anatoly Podgoretsky ©   (2004-10-17 18:41) [43]

default ©   (17.10.04 18:38) [41]
Ты не совсем прав, файлы Паскаля это высокоуровневая оболочка на системой и это не обязательно Виндоус.
Кроме того они или работают с понятиями строка, тип, блок, а не байт, как это у низкоуровневых библиотек, как АПИ так и TStream


 
Fay ©   (2004-10-18 04:15) [44]

2 VMcL ©   (17.10.04 18:41) [42]
Если не секрет, а нафиг? Что это даст при последовательной обработке?


 
VMcL ©   (2004-10-18 07:14) [45]

>>ИМХО ©  (17.10.04 18:22) [40]

Кстати, забыл, кроме FILE_FLAG_NO_BUFFERING, можно еще поиграться с FILE_FLAG_SEQUENTIAL_SCAN.

>>Fay ©  (18.10.04 04:15) [44]

Тут так сразу сложно ответить. Просто приведу выдержку из книги:
CreateFile Cache Flags
FILE_FLAG_NO_BUFFERING This flag indicates not to use any data buffering when accessing a file. To improve performance, the system caches data to and from disk drives. Normally you do not specify this flag, and the cache manager keeps recently accessed portions of the file system in memory. This way, if you read a couple of bytes from a file and then read a few more bytes, the file"s data is most likely loaded in memory, and the disk has to be accessed only once instead of twice, greatly improving performance. However, this process does mean that portions of the file"s data are in memory twice: the cache manager has a buffer, and you called some function (such as ReadFile) that copied some of the data from the cache manager"s buffer into your own buffer.

When the cache manager is buffering data, it might also read ahead so that the next bytes you"re likely to read are already in memory. Again, speed is improved by reading more bytes than necessary from the file. Memory is potentially wasted if you never attempt to read further in the file. (See the FILE_FLAG_SEQUENTIAL_SCAN and FILE_FLAG_RANDOM_ACCESS flags, discussed next, for more about reading ahead.)

By specifying the FILE_FLAG_NO_BUFFERING flag, you tell the cache manager that you do not want it to buffer any data—you take on this responsibility yourself! Depending on what you"re doing, this flag can improve your application"s speed and memory usage. Because the file system"s device driver is writing the file"s data directly into the buffers that you supply, you must follow certain rules:

You must always access the file by using offsets that are exact multiples of the disk volume"s sector size. (Use the GetDiskFreeSpace function to determine the disk volume"s sector size.)

You must always read/write a number of bytes that is an exact multiple of the sector size.

You must make sure that the buffer in your process"s address space begins on an address that is integrally divisible by the sector size.

FILE_FLAG_SEQUENTIAL_SCAN and FILE_FLAG_RANDOM_ACCESS These flags are useful only if you allow the system to buffer the file data for you. If you specify the FILE_FLAG_NO_BUFFERING flag, both of these flags are ignored.

If you specify the FILE_FLAG_SEQUENTIAL_SCAN flag, the system thinks you are accessing the file sequentially. When you read some data from the file, the system will actually read more of the file"s data than the amount you requested. This process reduces the number of hits to the hard disk and improves the speed of your application. If you perform any direct seeks on the file, the system has spent a little extra time and memory caching data that you are not accessing. This is perfectly OK, but if you do it often, you"d be better off specifying the FILE_FLAG_RANDOM_ACCESS flag. This flag tells the system not to pre-read file data.

To manage a file, the cache manager must maintain some internal data structures for the file—the larger the file, the more data structures required. When working with extremely large files, the cache manager might not be able to allocate the internal data structures it requires and will fail to open the file. To access extremely large files, you must open the file using the FILE_ FLAG_NO_BUFFERING flag.


 
panov ©   (2004-10-18 10:08) [46]

>Fay ©   (18.10.04 04:15) [44]

Если не секрет, а нафиг? Что это даст при последовательной обработке?

Система не будет использовать запись во внутренние буферы, а будет сразу отдавать данные приложению. За счет этого операция чтения будет выполняться быстрее(с точки зрения приложения).


 
Fay ©   (2004-10-19 12:11) [47]

2 panov ©   (18.10.04 10:08) [46]
Если склероз мне не изменяет, эта самая система читает из файла несколько больше, чем запросили.
Именно при последовательном доступе это дожно дать выигрыш.


 
panov ©   (2004-10-19 12:26) [48]

>Fay ©   (19.10.04 12:11) [47]
Если склероз мне не изменяет, эта самая система читает из файла несколько больше, чем запросили.

Нет, не несколько больше, а объем данных, пропорциональный размеру кластера.

Именно при последовательном доступе это дожно дать выигрыш.

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

Как раз этот флаг FILE_FLAG_NO_BUFFERING позволяет избежать этого промежуточного этапа в получении данных.


 
panov ©   (2004-10-19 12:32) [49]

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


 
Fay ©   (2004-10-19 13:21) [50]

2 panov ©   (19.10.04 12:32) [49]

> только замедляют работу при непрерывном
> последовательном чтении

Поверить в это не сложно, но видеть это замедление не приходилось.


 
panov ©   (2004-10-19 19:59) [51]

>Fay ©   (19.10.04 13:21) [50]

Прошу прощения - неправильно сформулировал.

При последовательном чтении всего файла буферизация только замедлит работу.



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2004.10.31;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.59 MB
Время: 0.038 c
14-1097372238
Думкин
2004-10-10 05:37
2004.10.31
С днем рождения! 10 октября


1-1098175993
Manfred8
2004-10-19 12:53
2004.10.31
Написание программатора для мини АТС


4-1095573471
Bil Bal Dur
2004-09-19 09:57
2004.10.31
Работа с LPT портом в XP


3-1096366410
bobsan
2004-09-28 14:13
2004.10.31
Кодировка при переносе dbase->mysql


4-1096373735
Th
2004-09-28 16:15
2004.10.31
Странное поведение функции TryEnterCriticalSection()





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский