![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Подскажите способ быстрой загрузки обычного текста [D5, Win2k]
Unknown user © (2004-07-13 17:51:00)При загрузке происходит разбивка на параграфы и копирование фрагмента загружаемого текста в строковую переменную, хранящую текст параграфа.
Fay (2004-07-16 18:53:00) [1]
> Ну, вообщем спасибо, буду работать дальше.
Не за что. Просто хотелось размяться на стандартной задачке - я по ним уже скучаю. 8)
> Насколько я понимаю твой способ чтения даст выигрыш в скорости
> не только для текстовых файлов. Это так?
С любыми. То, что ты работаешь с "текстовыми" файлами - частность.
Удачи.
Unknown user (2004-07-16 16:48:00) [2]To Fay.
Попробовал твой способ, работает минимум в 5 раз быстрее. За, что и благодарю. В твоем коде осталась еще одна ошибка, и небольшая неточность -текст в параграф надо копировать с символом возврата каретки. Но исправить это было делом 3-х минут.
Но, почему такой выигрыш в скорости? Я думал совсем необязательно отображать файлы в память для того, чтобы повысить скорость чтения, ведь если файл небольшой Windows считывает его в память целиком (наверное, даже при использовании буфера чтения меньше размера файла). Или AnsiStrScan медленно работает?
Насколько я понимаю твой способ чтения даст выигрыш в скорости не только для текстовых файлов. Это так?
Ну, вообщем спасибо, буду работать дальше.
Fay (2004-07-13 23:19:00) [3]Я бы сказал несколько ошибочек 8)
if p2 = #13 then
begin
Par := TParagraph.Create(Self);
Par.FFonts[0].EndChrInd := Length(Par.FText);
FParagraphs.Add(Par);
if p1 < p2 then
SetString(Par.FText, PChar(p1), p2 - p1);
Inc(p2);
if p2 < pe then
if p2^ = #10 then Inc(p2);
p1 := p2;
end
else
Inc(p2);
Fay (2004-07-13 23:10:00) [4]При вечернем обходе найдена ошибочка 8)
...
if p2 <> pe then
if p2 = #10 then Inc(p2);
p1 := p2 + 1;
...
Fay (2004-07-13 22:51:00) [5]М.б. не очень элегантно, но попробуй
var
h, m, sz : Cardinal;
v, p1, p2, pe : PChar;
begin
h := CreateFile('c:\YourFile.ext', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if h = INVALID_HANDLE_VALUE then Exit;
try
sz := GetFileSize(h, nil);
if sz = 0 then Exit;
m := CreateFileMapping(h, nil, PAGE_READONLY, 0, 0, 'BuBuBu');
if m = 0 then Exit;
v := MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
if v = nil then Exit;
p1 := v;
p2 := v;
pe := p1 + sz - 1;
while p2 <= pe do
begin
if p2 = #13 then
begin
Par := TParagraph.Create(Self);
if p1 < p2 then
SetString(Par.FText, PChar(p1), p2 - p1);
if p2 <> pe then
if p2 = #10 then Inc(p2);
p1 := p2;
Par.FFonts[0].EndChrInd := Length(Par.FText);
FParagraphs.Add(Par);
end;
Inc(p2);
end;
finally
if v <> nil then UnmapViewOfFile(v);
if m <> 0 then CloseHandle(m);
end;
Unknown user (2004-07-13 21:00:00) [6]To ASMiD.
Дело в том, что AnsiStrScan использует StrScan, а та в свою очередь написана на asm, значит должна работать быстрее, чем перебор символов в тексте по одному. А тип string в Делфи уже лет 10 не ограничен 255 символами (если конечно явно не указывать ShortString)
ASMiD (2004-07-13 20:44:00) [7]Ну очень мудрый код.
И как работать с S, если string-255 символов по максимуму.
В общем круто.
Попробуй все сделать в одном цикле с использованием if
for k1:=1 to Stream.Size-Stream.Position do begin
if s[k1]=#10 then
и тд
end;
Unknown user (2004-07-13 20:33:00) [8]To Anatoly Podgoretsky. TSringList не устраивает, поскольку текст хранится в иной структуре, а использовать только для загрузки нецелесообразно.
Главная проблема даже не в загрузке текста непосредственно, а в поиске символа разделения абзацев, выделении памяти под абзац, копировании текста (смотрите код).
Unknown user (2004-07-13 20:24:00) [9]Показываю код.
function EndLinePos(ALine:PChar):integer;
var P:PChar;
begin
P:=AnsiStrScan(ALine,#13);
if P=nil
then Result:=Length(ALine)
else Result:=P-ALine+1;
end;
function LoadFromStream(Stream:TStream):boolean;
var Len,Start,Stop:integer;
S:string;
Par:TParagraph;
begin
Len:=Stream.Size-Stream.Position;
SetString(S,nil,Len);
Stream.Read(Pointer(S)^,Len);
Start:=1; S:=S+#13;
while Start<Len do begin
Stop:=EndLinePos(PChar(@S[Start]))+Start;
Par:=TParagraph.Create(Self);
SetString(Par.FText,PChar(@S[Start]),Stop-Start);
Par.FFonts[0].EndChrInd:=Length(Par.FText);
FParagraphs.Add(Par);
if S[Stop]=#10 then Inc(Stop);
Start:=Stop;
end; {while}
end;
Текст размером 800 кб и в несколько тысяч абзацев на Athlon 1600+ загружается 13 сек. Как оптимизировать?
Anatoly Podgoretsky (2004-07-13 20:23:00) [10]А использовать текстовые файлы Паскали или загрузку в TSringList не устраивает
ASMiD (2004-07-13 19:53:00) [11]Помоему для быстрого копирования ничего лучше Move(Sou,Dest,Siz) не придумали.
Reindeer Moss Eater (2004-07-13 19:52:00) [12]Это то, чего ты ищешь.
Unknown user (2004-07-13 19:51:00) [13]To Семен Сорокин. А что такое QuickLoad?
Fay (2004-07-13 19:51:00) [14]2Unknown user © (13.07.04 19:49) [4]
Покажите ВАШ код.
Unknown user (2004-07-13 19:50:00) [15]To Digitman. Параграф в смысле текстовый абзац.
Unknown user (2004-07-13 19:49:00) [16]To Reindeer Moss Eater
1. Из текстового файла.
2. В свой компонент (читай в память)
Тормозящие факторы:
1. Поиск символа #13 (конец абзаца)
2. Копирование фрагмента текста с текущей позиции до найденного символа #13 в строковую переменную, хранящую текст абзаца.
Семен Сорокин (2004-07-13 18:03:00) [17]2Unknown user
надо QuickLoad использовать
Digitman (2004-07-13 17:54:00) [18]
> параграфа
"параграф" - определение достойно подробностей ? как думаешь ?
Reindeer Moss Eater (2004-07-13 17:52:00) [19]При загрузке происходит разбивка ...
При загрузке откуда?
При загрузке куда?