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

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

Быстрый доступ к файлу [D7]


Страницы:   1 2

pirate ©   (2006-05-24 21:15:00) 

Уважаемые мастера!
Пожалуйста, посоветуйте самый быстрый способ побайтового чтения всего файла (Он у меня 16 Мб, загружается около 2 минут). А вот к примеру Lingvo загружает свою базу слов практически мгновенно. Как бы и мне ускорить процесс чтения из файла?


pirate   (2006-05-29 15:37:00) [1]

Хочу поблагодарить всех участников обсуждения: загрузка проходит за 0.11 сек. Спасибо!


tytus   (2006-05-26 15:41:00) [2]

han_malign[20] правильно пишет. Я сам давно ТОЛЬКО так работаю - файлы размером в 160 метров обрабатываются на раз. Для поиска нужного слова использую StrPos, которая возвращает указатель на найденное слово. Начало отображения описываю как PByte. Очень просто работать:INC, DEC. Если нужно скопировать строку (слово) - использую MOVE. Довольно хорошо эту тему описали Ксавье и Пачеко.


pirate   (2006-05-26 15:22:00) [3]


> Имеем структуру :
> RDicWord = record // Можно поиграть упаковкой
> OffSet : Int64;
> Length : DWord;
> end;
> Обявляем динамический массив :
> DicWordList : array of RDicWord;


Разве на написано:

> type TWord=record
> wOFF:int64; //
> wLEN:byte; // сдвиг и длина самого слова
> dOFF:int64;
> dLEN:integer; // сдвиг и длина его описания
> end;
>
> type TDict=record
> count:longint;
> words:array of TWord; // динамический массив записей
> end;


Я ведь так и делаю.
http://www.delphimaster.ru/articles/dyntable/index.html
Вот это действительно тема!


ANB   (2006-05-25 16:08:00) [4]

Да, всеь словарь можно хранить и просто в длинной строке. Тогда точно будет работать. А ползать по словарю можно через указатели на RDicWord.


ANB   (2006-05-25 16:07:00) [5]

Значится, вариант решения задачи.
Сами слова в словаре не храним - это хорошо, следовательно, описание слова имеет фиксированнуб длинну.
Имеем структуру :
RDicWord = record // Можно поиграть упаковкой
OffSet : Int64;
Length : DWord;
end;
Обявляем динамический массив :
DicWordList : array of RDicWord;
Узнаем размер файла (FileSeek). Делим длинну на размер записи SizeOf(RDicWord). Обрабатываем некруглую длинну (проще отбросить лишние байты в файле).
Устанавливаем длинну массива DicWordList. И за одну операцию чтения прямо в него загружаем содержимое файла.
Все имхо, мог чего и напутать. Критики - поправьте плиз.


han_malign   (2006-05-25 15:53:00) [6]

упс: len:= i - offs;
- это другая len, не та что (i<len)... :)


han_malign   (2006-05-25 15:52:00) [7]


> s1:=s1+buf[i];
> if (c1=#13)and(c2=#10) then // проверка на "новую строку"
> begin
>        p:=pos('#',s1);
>        q:=length(s1);

i:= 0;
while(i < len)do begin
   while((i < len)and(buf[i] in [ #10, #13]))do inc(i);
   offs:= i;
   while((i < len)and(not(buf[i] in [ #10, #13, '#'])))do inc(i);
   dush:= i - offs;
   while((i < len)and(not(buf[i] in [ #10, #13])))do inc(i);
   len:= i - offs;
   with D.words[D.count-1] do begin
        ...
   end;
end;

- примерно так, а операции со строками(изменение, поиск) - тоже не маленькие, и весьма...


han_malign   (2006-05-25 15:40:00) [8]


> файлы, отображаемые в память  посмотрите, плиз..

- 4-и раз вставлять не буду - смотри тут
http://www.delphimaster.ru/cgi-bin/forum.pl?n=0&id=1146027596&p=2
- 16 Мб - халява, спокойно целиком отмапируется...


IOs   (2006-05-25 15:24:00) [9]

файлы, отображаемые в память  посмотрите, плиз..
Конечно, это не побайтово :-), но все же...


Loginov Dmitry   (2006-05-25 15:15:00) [10]

pirate ©   (25.05.06 13:25) [17]
Потом еще много чего оптимизировал, добился загрузки за 22 сек


Вам еще много чего придется оптимизировать. Нормальная скорость загрузки для вашего случая не должна превышать одной секунды.


pirate   (2006-05-25 13:25:00) [11]

Спасибо большое.
Я переделал функцию для TFileStream.
заработала быстрее.
Длину хранить в начале я не могу. Придумал вот что:
Сделал заведомо большой размер, а после загрузки уменьшаю его до необходимого.А если в процессе загрузки размера не хватает, то начинаем его увеличивать...

Заработала во много раз быстрее. Потом еще много чего оптимизировал, добился загрузки за 22 сек. Но и это многовато.
Я взял и сохранил количество и сдвиги всех записей в отдельном файле, что-то вроде индексного файла в 1С Бухгалтерии.

Но вот в чем проблема:
Написал функцию, которая делает seek  по сдвигу и считывает Len байт.

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

Почему так?
Из-за seek'а в цикле?


Romkin   (2006-05-25 12:17:00) [12]

pirate ©   (24.05.06 22:41) [11] Делай что хочешь, но наращивать длину на 1 в цикле - эффектное убийство памяти :)
Есть же TList, TStringList и тд.
http://www.delphimaster.ru/articles/dyntable/index.html
Читай первые несколько абзацев.
Подсказка: хотя там для строк, но все действительно и для массива


Loginov Dmitry   (2006-05-25 08:52:00) [13]

Leonid Troyanovsky ©   (24.05.06 23:21) [14]

Была какая-то сверх-точная, но сверх-сложная формула для вычисления разов. Она говорит, что "по крайней мере в два". Найду - выложу :)))


Leonid Troyanovsky   (2006-05-24 23:21:00) [14]


> Loginov Dmitry ©   (24.05.06 22:55) [13]

> чтения рекомендую использовать TMemoryStream. По крайней
> мере в пару раз скорость загрузки должна


А почему именно в два?
А не, скажем, в полтора?

--
Regards, LVT.


Loginov Dmitry   (2006-05-24 22:55:00) [15]

Ваш файл не очень большой (16 Мбайт), поэтому для ускорения чтения рекомендую использовать TMemoryStream. По крайней мере в пару раз скорость загрузки должна увеличиться (по сравнению с BlockRead).


Джо   (2006-05-24 22:48:00) [16]

> [11] pirate ©   (24.05.06 22:41)
> Но я ведь теоретически не знаю размер словаря, для того
> и динамический массив. А так я сразу мог бы сделать статический
> массив.

Один из вариантов: хранить длину массива в файле, перед данными. То есть, алгоритм сведется к следующему: прочитать из файла длину массива, установить ее (один раз!) и далее в уже заданный массив считывать сами данные.


pirate   (2006-05-24 22:41:00) [17]

Но я ведь теоретически не знаю размер словаря, для того и динамический массив. А так я сразу мог бы сделать статический массив.


Джо   (2006-05-24 22:39:00) [18]

Все дело в SetLength. Нужно сделать так, чтобы длину дин. массива задавать один раз.


pirate   (2006-05-24 22:21:00) [19]

Странно.
Что может быть причиной томозов?
Может потому что я использую динамический массив?
Кстати, следует отметить, что у меня сначала дело идет быстро, а потом начинает тормозить, все сильнее и сильнее.
Я хочу загрузить в программу эту самую структуру словаря.
Словарь представлен в виде:
СЛОВО#Описание
СЛОВО#Описание и т д

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

type TWord=record
wOFF:int64; //
wLEN:byte; // сдвиг и длина самого слова
dOFF:int64;
dLEN:integer; // сдвиг и длина его описания
end;

type TDict=record
count:longint;
words:array of TWord; // динамический массив записей
end;

procedure LoadDict(path:string;var D:TDict);
var
 FromF: file;
 NumRead: Integer;
 Buf: array[1..512] of Char;
 c1,c2,c3,c4,c5:char;
 i,j:integer;
 k:int64;
 s1,s2,s3:string;
 B,p,q:integer;
begin

k:=1; // общий сдвиг, необходимый для рассчетов.
B:=0;
s1:='';
c1:=#0;
c2:=#0;
...................................
for i:=1 to numread do
       begin
       c1:=c2;
       c2:=buf[i];
       s1:=s1+buf[i];
       if (c1=#13)and(c2=#10) then // проверка на "новую строку"
       begin
       p:=pos('#',s1);
       q:=length(s1);
         D.count:=D.count+1;
         SetLength(D.words,D.count);
         D.words[D.count-1].wOFF:=k;
         D.words[D.count-1].wLEN:=p-1;
         D.words[D.count-1].dOFF:=k+p;
         D.words[D.count-1].dLEN:=q-p-3; // записываем координаты нужных строк.
         rd:=d.count;
         if (rd mod 1000)=0 then //раз в тысячу слов делаем ProcessMesages
         begin
         form1.Caption:=inttostr(rd)+' '+copy(s1,1,p-1);
         application.ProcessMessages;
         end;
         k:=k+q;
         s1:='';
       end;
       end;
.....................


pirate   (2006-05-24 21:56:00) [20]

Ладно, спасибо большое!


Страницы:   1 2

Наверх

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