![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Быстрое чтение файла [D5, Win95/98]
Кастуся © (2004-06-21 22:46:00)мастера, хелп!
обрабатываю файл "дедовским" методом: построчно читаю данные и со строкой делаю все необходимое.
Но не устраивает скорость. На P-I-133 файл в обрабатывает за . Можно ли увеличить скорость на стадии чтения? (Обработка прочитанной строки оптимизированна до максимума) Я знаю, использовать либо BlockRead либо TFileStream но там надо читать буферами, для этого надо знать где строка заканчивается. А можно как-нибудь построчно читать?
Хотел попробовать сл. код:
Start := Stream.Position;
End := Start;
Repeat
Stream.Read(Buffer^, 1024);
CRPos := FindCR(Buffer^); { где FindCR возвращает 0..1023 для CR,
и 1024, если он не найден}
Inc(End, CRPos);
Until CRPos < 1024;
GetMem(MyPChar, End - Start); { Здесь может быть +-1 -- мне лень сегодня проверять! }
Stream.Seek(Start);
Stream.Read(MyPChar^, End - Start)
но что такое FindCR?
В общем как тут быть. Дело срочное, хелп плиз!!!
Romkin (2004-06-28 12:11:00) [1]Вот, пожалуйста. Разбирайся, должно работать.
Понятно, Lines должны быть созданы до вызова процедуры...
type
TAutoState = (auWaitIdent, auInIdent, auReadMsg);
const
Ident: string = 'MESSAGE:';
EndStrChars: set of char = [ #13,#10];
ExceptChars: set of char = [' ']; //Строка без этих символов
procedure GetMsgStrings(const FileName: string; Lines: TStrings);
var
F: file of char;
auState: TAutoState;
IdLen: Integer;
IdPos: Integer;
ch: char;
MsgStr: string;
begin
idLen := Length(Ident);
MsgStr := '';
assignFile(F, FileName);
reset(F);
try
auState := auWaitIdent;
while not EOF(F) do
begin
Read(F, ch);
case auState of
auWaitIdent: begin //Ждем 'MESSAGE:'
if ch = Ident[1] then //первый символ, однако
begin
idPos := 1;
auState := auInIdent;
//На тот случай, если длина Ident = 1
if idPos = idLen then //Ident найден
auState := auReadMsg;
end;
end;
auInIdent: begin //Проверяем, однако, совпадение
Inc(idPos);
if (ch = Ident[idPos]) and (idPos = idLen) then
auState := auReadMsg
else
if ch <> Ident[idPos] then //Это не ident
auState := auWaitIdent;
//увы, только одно состояние :(
//На случай попадания MESMESSAGE: и тд
if (ch = Ident[1]) and (auState <> auInIdent) then
begin
idPos := 1;
auState := auInIdent;
end;
end;
auReadMsg: begin
if not (ch in EndStrChars) then //Конца строки нет
begin
if not (ch in ExceptChars) then //все, кроме пробела
MsgStr := MsgStr + ch;
end
else
begin
auState := auWaitIdent;
Lines.Add(MsgStr);
MsgStr := '';
end
end;
end; //case
end; //while
finally
CloseFile(F);
end;
end;
Romkin (2004-06-28 11:23:00) [2]Кастуся (27.06.04 09:32) [80] Не все так просто :))
Надо полностью определить правила. Лучше бы реальный пример привел, на первый взгляд, твой случай решается детерминированным автоматом, а то, что ты с message привел - недетерминированным удобнее ;)
Впрочем, эскиз набросать могу. Итак, есть текстовый файл, процедура должна заполнить TStrings частями строк, идущими после 'MESSAGE:' и до конца строки, удалив пробелы. Символы между идентификатором и концом строки - любые.
Так пойдет? :)) Сейчас будет...
Anatoly Podgoretsky (2004-06-27 11:56:00) [3]Поток длеко не непрерывный, а разбит на строки.
Кастуся (2004-06-27 09:55:00) [4]
> Romkin © (25.06.04 16:36) [78]
вся штука в том, как в этом непрерывном потоке найти идентификационную строку?
или ты предлагаешь считывать строки методом
while not eof(f) do
begin
readln(f,st);
if pos('MESSAGE',st)>0 then
использовать конечный автомат
end;
так?
Кастуся (2004-06-27 09:32:00) [5]Снова чуть-чуть продолжим
> Romkin © (25.06.04 16:36) [78]
Если считывать файл побайтно, возникает проблема с определением положения троки идентификатора. Вот задача:
в общем случае есть в тексте сообщение вида:
MESSAGE: ## ## ## ## ## ##;
Необходимо его идентифицировать и получить, то что находится вместо #. Вот. как это реализ с пом-ю конечн автомата?
Кастуся (2004-06-25 18:39:00) [6]классно конечно
Ладно всем спасибо!!!
Romkin (2004-06-25 16:36:00) [7]>А можно пару слов про "конечный автомат"? Что енто такое и с чем его едят?
НУ я же уже давал:
Romkin © (23.06.04 18:09) [31]
Основная идея простая: файл рассматривается как непрерывный поток байт, каждый из которых проходит через "фильтр", который реагирует на него изменением состояния (и данных). В результате - DelSpaces, например, вообще не нужна будет, реакция на пробел простая - continue :))
Fay (2004-06-25 16:32:00) [8]2Кастуся (25.06.04 15:57) [75]
> А можно пару слов про "конечный автомат"? Что енто такое
> и с чем его едят?
Вам не стыдно, товарищ? Интернет забит подобной инфой. Да и институте не умалчивают 8)
Anatoly Podgoretsky (2004-06-25 16:03:00) [9]Они могли работать в крайнем ограниченом количестве случаев, в большинстве случаев должны приводить к ошибке, хорошо если не критической.
Кастуся (2004-06-25 15:57:00) [10]
> Romkin © (25.06.04 11:29) [74]
Может тебе интересно, конечно, что у меня за задача, но, еаверное, ИМХО лень будет тебе что-нибудь делать. В принципе, из этой ветки я извлек для себя массу полезного, благодаря чему, скорость работы моего алгоритма увеличилась в несколько раз.
> почему бы просто не делать кусочную оптимизацию, а переписать
> все на конечный автомат?
А можно пару слов про "конечный автомат"? Что енто такое и с чем его едят?
Так что спасибо огромное всем за помощь!
> Anatoly Podgoretsky © (25.06.04 10:25) [73]
а асм коды чьи-то там все равно не работали!
Romkin (2004-06-25 11:29:00) [11]Упс... Все почистили. Зачем же красный карандаш, когда синего было достаточно?!
Кастуся (24.06.04 17:12) [66] Да, именно определяет расход времени на разные функции. GPProfile, например. НАйти можно, достаточно поискать Delphi profiler ;)
И, кстати, почему бы просто не делать кусочную оптимизацию, а переписать все на конечный автомат? Уверяю, скорее всего быстрее, чем автомат ты вряд ли сделаешь.
И я уже пару раз просил дать постановку, а что собственно требуется-то? Улучшать код надо разумно, и, на мой взгляд, лезть в дебри ассемблера и проблемно-зависимой оптимизации кода надо в крайнем случае. Если скорость универсального короткого кода не устраивает, прежде всего надо посмотреть, нельзя ли сам алгоритм улучшить
Anatoly Podgoretsky (2004-06-25 10:25:00) [12]Неправильное использоние регистров, в результате могут быть выполнены недопустимые вещи, абсольтно любые и AV самое легкое что может произойти. Код абсолютно безграмотен, именно все приведеные с использование ассемблера.
Кастуся (2004-06-25 10:08:00) [13]Так чем?
Кастуся (2004-06-24 22:01:00) [14]
> Anatoly Podgoretsky © (24.06.04 21:13) [70]
> Слушай не лез бы ты в ассемблер, который раз по счету приводишь
> грубый и чрезвычайно опасный код. Ты бы хоть раз прочитал
> справку про встроеный ассемблер и соглашения.
а чем приведённый код може быть опсаным?
Anatoly Podgoretsky (2004-06-24 21:13:00) [15]Слушай не лез бы ты в ассемблер, который раз по счету приводишь грубый и чрезвычайно опасный код. Ты бы хоть раз прочитал справку про встроеный ассемблер и соглашения.
(2004-06-24 20:30:00) [16]Удалено модератором
Примечание: Смени ник.
(2004-06-24 19:21:00) [17]Удалено модератором
Примечание: Смени ник
Кастуся (2004-06-24 18:35:00) [18]короче пробовал я StrToInt64 - медленно работает
Кастуся (2004-06-24 17:12:00) [19]
> Romkin © (24.06.04 11:21) [50]
> ЛУчше посмотреть на другие участки программы...
> А еще лучше воспользоваться профилировщиком
А что такое профилировщикик? Это я так понимаю поределяет что сколько времени занимет в программе? Это какая-то программа и где её достать?
> Romkin © (24.06.04 11:28) [52]
> Кстати, насколько я понял, тебе значение строки не нужно?
> Тогда StrToInt64, но разбей строку на две половины - как
> раз влезет.
Я вот ут думаю, а будет ли это все быстрее работать, чем просто
HexSt:='0'+'1'+'2'+'3'+'4'+'5'+'6'+'7'+'8'+'9'+'a'+'b'+'c'+'d'+'e'+'f';
Bad:=not (LastDelimiter(HexSt,w0)=32);
Fay (2004-06-24 14:31:00) [20]Пляски с sz в SetActive - левые 8)