Notes |
|
|
Не считывать файл полностью в память, а читать постепенно прямо из файла |
|
|
(0010654)
|
zed
|
27-02-2013 13:57
|
|
Просто нужно читать файл построчно. Там такой формат, что одна строка - один населённый пункт. Очень удобно.
// Open existing text file and show first line
procedure ReadTxt;
var
F: Textfile;
str: string;
begin
AssignFile(f, 'c:\ek.txt'); {Assigns the Filename}
Reset(f); {Opens the file for reading}
Readln(f, str);
ShowMessage('1. line of textfile:' + str);
Closefile(f); {Closes file F}
end; |
|
|
(0010655)
|
Garl
|
27-02-2013 14:00
|
|
построчно не проиграем в производительности?
и в файле конец строки задан одним символом $0A |
|
|
(0010656)
|
zed
|
27-02-2013 14:09
|
|
Сильно не проиграешь. А можешь и наоборот выиграть, если искомая комбинация будет найдена где-нибудь в начале файла.
Ещё, как вариант, можно открывать файл как MemoryMapped - тогда винда прозрачно оптимизирует считывание данных из файла. Но придётся работать с PChar и вручную искать конец строки. |
|
|
(0010657)
|
Garl
|
27-02-2013 14:12
|
|
ну мы и так вручную ищем КонецСтроки
есть пример работы с MemoryMapped? |
|
|
(0010658)
|
zed
|
27-02-2013 14:22
|
|
Прикрепил юнит.
Использовать можно как-то так:
VFile := TMappedFile.Create('c:\test.txt');
VData := PByte(VFile.Content);
for I := 0 to VFile.Size - 1 do begin
if VData^ = $0A then begin
// найден конец строки
end;
Inc(VData);
end;
VFile.Free;
|
|
|
(0010760)
|
vasketsov
|
02-03-2013 09:16
(edited on: 02-03-2013 09:17) |
|
Есть подозрение, что можно читать блоками скажем по 4k. Всё равно системный кэш будет поднимать с диска такими (или аналогичными в соответствии с настройками оси и железа) блоками. Ну и в этом случае ищется либо начало искомого текста либо конец строки (если нашлось начало текста - ищем после него конец строки, при необходимости подгружая следующий блок, потом проверяем что нашли искомое, нет - перепрыгиваем на длину искомой строки и продолжаем), и вся эта котовасия покуда или не найдётся или файл не кончится. Хотя может там сложнее формат, и так не получится.
А посрочно конечно медленно, да и делает RTL то же самое примерно, поднимает с диска в кэш и ищет конец строки, выплёвывает их покуда есть чего, не зная ни о формате, ни о том, насколько можно упростить проверку, чего нашли.
В любом случае чиать весь гиговый файл враз конечно неправильно.
|
|
|
|
>В любом случае чиать весь гиговый файл враз конечно неправильно.
Как и мапить его целиком в адресное пространство.
Нужно сделать нормальное чтение, например с буферизацией при помощи MapViewOfFile по кускам. |
|
|
(0010762)
|
zed
|
02-03-2013 10:37
(edited on: 02-03-2013 10:49) |
|
Мне почему-то казалось, что винда должна была сама мапить файл по-странично (теми же кусками по 4k), с периодическим сбрасыванием ненужных страниц. Но почему-то всё не так (:
Похоже, что периодический вызов VirtualUnlock мог бы решить проблему:
http://stackoverflow.com/questions/1880714/createfilemapping-mapviewoffile-how-to-avoid-holding-up-the-system-memory/1882478
|
|
|
|
Не понимаю как VirtualUnlock может помочь в этом, это вообще "из другой оперы". Когда мапится файл, создаётся объект типа "секция" (ZwCreateSection+ZwMapViewOfSection), до Mm от него как до Луны в известной позе.
>с периодическим сбрасыванием ненужных страниц
А откуда известно, что страницы больше не нужны?
зы. Я б ограничился обычным файловым чтением в статический буфер, файл открывается для последовательного чтения, буфер дописывается в string, и далее поиск, ещё поиск, ещё поиск, не нашли - ещё читаем буферок, и т.п... зачем тут файл-то маппить в память? |
|
|
(0010765)
|
zed
|
02-03-2013 11:10
|
|
>А откуда известно, что страницы больше не нужны?
Никто в них в данный момент времени не пишет/не читает = не нужны.
>зачем тут файл-то маппить в память?
Предполагалось, что не будет жрать память и не нужно с буферками напрягаться. |
|
|
|
>Никто в них в данный момент времени не пишет/не читает
Ну они если и упадут, то только в своп (секция-то не меняется, и размер её не меняется, и атрибуты страниц тоже, так что вытеснены они могут быть на общих основаниях). Вот и осталось понять зачем это, тем более что всё равно это не панацея и не избавляет от возни с буферами.
>и не нужно с буферками напрягаться
А всё равно нужно будет напрягаться. Доступ-то последовательный. Соответственно если граница буфера попадает посередине искомого слова - "напряжение" и возникает, чтение следующего, стыковка, поиск и т.п.
К сожалению я не знаю простой нормальный системный способ открыть файл для последовательного доступа на чтение и тянуть его построчно, ограничив размер "окошка" и не долбясь с буферами, даже на Native NT API. |
|