Текущий архив: 2004.08.01;
Скачать: CL | DM;
ВнизПодскажите способ быстрой загрузки обычного текста Найти похожие ветки
← →
Unknown user © (2004-07-13 17:51) [0]При загрузке происходит разбивка на параграфы и копирование фрагмента загружаемого текста в строковую переменную, хранящую текст параграфа.
← →
Reindeer Moss Eater © (2004-07-13 17:52) [1]При загрузке происходит разбивка ...
При загрузке откуда?
При загрузке куда?
← →
Digitman © (2004-07-13 17:54) [2]
> параграфа
"параграф" - определение достойно подробностей ? как думаешь ?
← →
Семен Сорокин © (2004-07-13 18:03) [3]2Unknown user
надо QuickLoad использовать
← →
Unknown user © (2004-07-13 19:49) [4]To Reindeer Moss Eater
1. Из текстового файла.
2. В свой компонент (читай в память)
Тормозящие факторы:
1. Поиск символа #13 (конец абзаца)
2. Копирование фрагмента текста с текущей позиции до найденного символа #13 в строковую переменную, хранящую текст абзаца.
← →
Unknown user © (2004-07-13 19:50) [5]To Digitman. Параграф в смысле текстовый абзац.
← →
Fay © (2004-07-13 19:51) [6]2Unknown user © (13.07.04 19:49) [4]
Покажите ВАШ код.
← →
Unknown user © (2004-07-13 19:51) [7]To Семен Сорокин. А что такое QuickLoad?
← →
Reindeer Moss Eater © (2004-07-13 19:52) [8]Это то, чего ты ищешь.
← →
ASMiD (2004-07-13 19:53) [9]Помоему для быстрого копирования ничего лучше Move(Sou,Dest,Siz) не придумали.
← →
Anatoly Podgoretsky © (2004-07-13 20:23) [10]А использовать текстовые файлы Паскали или загрузку в TSringList не устраивает
← →
Unknown user © (2004-07-13 20:24) [11]Показываю код.
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 сек. Как оптимизировать?
← →
Unknown user © (2004-07-13 20:33) [12]To Anatoly Podgoretsky. TSringList не устраивает, поскольку текст хранится в иной структуре, а использовать только для загрузки нецелесообразно.
Главная проблема даже не в загрузке текста непосредственно, а в поиске символа разделения абзацев, выделении памяти под абзац, копировании текста (смотрите код).
← →
ASMiD (2004-07-13 20:44) [13]Ну очень мудрый код.
И как работать с 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 21:00) [14]To ASMiD.
Дело в том, что AnsiStrScan использует StrScan, а та в свою очередь написана на asm, значит должна работать быстрее, чем перебор символов в тексте по одному. А тип string в Делфи уже лет 10 не ограничен 255 символами (если конечно явно не указывать ShortString)
← →
Fay © (2004-07-13 22:51) [15]М.б. не очень элегантно, но попробуй
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;
← →
Fay © (2004-07-13 23:10) [16]При вечернем обходе найдена ошибочка 8)
...
if p2 <> pe then
if p2 = #10 then Inc(p2);
p1 := p2 + 1;
...
← →
Fay © (2004-07-13 23:19) [17]Я бы сказал несколько ошибочек 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);
← →
Unknown user © (2004-07-16 16:48) [18]To Fay.
Попробовал твой способ, работает минимум в 5 раз быстрее. За, что и благодарю. В твоем коде осталась еще одна ошибка, и небольшая неточность -текст в параграф надо копировать с символом возврата каретки. Но исправить это было делом 3-х минут.
Но, почему такой выигрыш в скорости? Я думал совсем необязательно отображать файлы в память для того, чтобы повысить скорость чтения, ведь если файл небольшой Windows считывает его в память целиком (наверное, даже при использовании буфера чтения меньше размера файла). Или AnsiStrScan медленно работает?
Насколько я понимаю твой способ чтения даст выигрыш в скорости не только для текстовых файлов. Это так?
Ну, вообщем спасибо, буду работать дальше.
← →
Fay © (2004-07-16 18:53) [19]
> Ну, вообщем спасибо, буду работать дальше.
Не за что. Просто хотелось размяться на стандартной задачке - я по ним уже скучаю. 8)
> Насколько я понимаю твой способ чтения даст выигрыш в скорости
> не только для текстовых файлов. Это так?
С любыми. То, что ты работаешь с "текстовыми" файлами - частность.
Удачи.
Страницы: 1 вся ветка
Текущий архив: 2004.08.01;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.038 c