![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как сократить время выполнения процедуры? [D7, XP]
Tatiana © (2006-02-04 21:59:00)Необходимо прочитать данные из *.txt файла. Данные структурированы. Проблема в том, что если количество строк большое (больше 10 000), то файл открывается недостаточно быстро. Каккие могут быть варианты, чтобы процедура выполнялась быстрее?
vovnuke (2006-02-08 17:15:00) [21]а что если с этой структурой работать с помощью ClientDataSet, а из него уже сохранять в файл?
Alex_C (2006-02-08 17:08:00) [22]Тебе уже ответили - тут выход один
ReadBlock и читать ну скачем по 64000 байта за раз.
Кстати недавно столкнулся с проблемой - надо было в базу переконвертировать текстовый фаил размером 19 мег. Так никакие TStringList.LoadFromFile и затем работа в памяти не помогли - очень долго, а вот читать как бинарный фаил блоками - наиболее быстро. Только по строкам прийдется тебе самому разбивать.
Tatiana (2006-02-08 16:57:00) [23]А кроме оптимизации кода, могут быть еще какие-нибудь варианты, чтобы заадча выполнялась быстрее. Дело в том, что ни один из вариантов, указанных выше, все равно по времени не отличается :(
Tatiana (2006-02-06 16:14:00) [24]Да, вы правы. Перед разделением строки я заменяю все разделители на пробелы, единственно, не меняю их количество, т.е. если было три табуляции, после выполнения функции они превращаются в три пробела.
Desdechado (2006-02-06 10:52:00) [25]основное время уходит не на чтение из файла, а на операции по разрезанию строк
подозреваю, что количество табуляций/пробелов и прочего между числами плавающее (для визуального выравнивания в файле)
тогда нужно их позаменять на нормальный разделитель одного формата (например, табуляцию) StringReplace, а уж после этого применять SplitString
Gero (2006-02-05 23:43:00) [26]> Насколько я понимаю "." и "," тоже относятся к Delimiter?
Delimiter передается аргументом в функцию и может быть каким угодно на твое усмотрение.
Tatiana (2006-02-05 23:10:00) [27]Насколько я понимаю "." и "," тоже относятся к Delimiter? Если так, то процедура не подходит, т.к. в строке есть числа в виде десятичных дробей. Процедура SplitString отделит целые части от десятичных, а мне нужно все число. Я права???
Gero (2006-02-05 22:17:00) [28]> begin...end © (05.02.06 22:09)
Да, согласен, спасибо :)
Код старый и сюда был бездумно скопирован )
begin...end (2006-02-05 22:09:00) [29]> Gero © (05.02.06 22:01) [14]
procedure SplitString(const Str: string; Delimiter: Char; Strings: TStrings);
begin
Strings.Delimiter := Delimiter;
Strings.DelimitedText := Str
end
Gero (2006-02-05 22:01:00) [30]
procedure SplitString(const Str: string; Delimiter: Char; Strings: TStrings);
var
s: string;
Pos, Pos2: Integer;
begin
Strings.BeginUpdate;
try
Strings.Clear;
Pos := 1;
for Pos2 := 1 to Length(Str) do begin
if Str[Pos2] = Delimiter then begin
s := Copy(Str, Pos, Pos2 - Pos);
Strings.Add(s);
Pos := Pos2 + 1;
end;
end;
s := Copy(Str, Pos, Length(Str) - Pos + 1);
Strings.Add(s);
finally
Strings.EndUpdate;
end;
end;
(c) DMClient team
Функция заносит подстроки в строке, разделенные Delimiter в Strings.
Надеюсь, с чтением файла построчно проблем не возникнет.
Tatiana (2006-02-05 21:35:00) [31]Файл заранее обработан таким образом, что в нем только цифры и , может быть слова (Name,Discriptoin), шапки нет, цифры (в смысле, поля) м.б. разделены пробелом, либо табуляцией, строки - вводом.
Desdechado (2006-02-05 21:17:00) [32]> Структура строки в *.txt файле:
не виду структуры, вижу только, что туда записано
структура подразумевает еще и "как записано"
т.е. должен быть указан формат, чем разделены поля, чем разделены строки, есть ли "шапка" и т.п.
Tatiana (2006-02-05 20:52:00) [33]Структура строки в *.txt файле:
Name X Y Z Description,
где Name и Description – String, а X, Y, Z – числа, с которыми впоследствии будут производиться математические преобразования.
У меня есть три варианта процедуры чтения файла, но по времени выполнения они не отличаются.
procedure TPoints.ReadPoints(aFileName: String); var
j: integer;
s,St : String;
Point: RPoint;
F: TextFile;
begin
try
AssignFile(F, aFileName);
Reset(F);
While not(Eof(F)) do
begin
Readln(F, s);
s := TrimLeft(s);
s := TabToSpace(s);
s := DotToDecSep(s);
if s <> '' then
begin
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.Name := St;
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.X := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.Y := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
if j > Length(s) then Break;
St := St + s[j];
j := j+1;
end;
Point.Z := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While j <= Length(s) do
begin
St := St + s[j];
j := j+1;
end;
Point.Discription := St;
AddPoint(Point);
end;
end;
except on E:Exception do
DoOnError (peReadError) ;
end;
CloseFile(F);
end;
procedure TPoints.ReadPoints(aFileName: String); var
j, i: integer;
s,St : String;
Point: RPoint;
List: TStringList;
begin
try
List := TStringList.Create;
List.LoadFromFile(aFileName);
i := 0;
While i <= List.Count - 1 do
begin
s := List[i];
s := TrimLeft(s);
s := DotToDecSepSpace(s);
if s <> '' then
begin
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.Name := St;
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.X := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
St := St + s[j];
j := j+1;
end;
Point.Y := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While s[j] <> ' ' do
begin
if j > Length(s) then Break;
St := St + s[j];
j := j+1;
end;
Point.Z := StrToFloat(St);
s := TrimLeft(RightStr(s, (Length(s)-Length(St))));
St := '';
j := 1;
While j <= Length(s) do
begin
St := St + s[j];
j := j+1;
end;
Point.Discription := St;
AddPoint(Point);
end;
i:= i + 1
end;
except on E:Exception do
DoOnError (peReadError) ;
end;
List.Free;
end;
procedure TPoints.ReadPoints(aFileName: String); var
i : integer;
s : String;
Point: RPoint;
List: TStringList;
begin
try
List := TStringList.Create;
List.LoadFromFile(aFileName);
i := 0;
While i <= List.Count - 1 do
begin
s := List[i];
s := Trim(s);
s := DotToDecSepSpace(s);
if s <> '' then
begin
Point.Name := LeftStr(s, Pos(' ', s) - 1);
s := TrimLeft(RightStr(s, (Length(s)-Pos(' ', s))));
Point.X := StrToFloat(LeftStr(s, Pos(' ', s) - 1));
s := TrimLeft(RightStr(s, (Length(s)-Pos(' ', s))));
Point.Y := StrToFloat(LeftStr(s, Pos(' ', s) - 1));
s := TrimLeft(RightStr(s, (Length(s)-Pos(' ', s))));
if Pos(' ', s) = 0 then
Point.Z := StrToFloat(s)
else
begin
Point.Z := StrToFloat(LeftStr(s, Pos(' ', s) - 1));
s := TrimLeft(RightStr(s, (Length(s)-Pos(' ', s))));
Point.Discription := s;
end;
AddPoint(Point);
end;
i:= i + 1
end;
except on E:Exception do
DoOnError (peReadError) ;
end;
List.Free;
end;
Anatoly Podgoretsky (2006-02-05 16:45:00) [34]Объем менее одного мегабайта, любой метод загрузки будет мгновенный, хоть в StringList
Tatiana (2006-02-05 16:14:00) [35]подождите, не гадайте :) я как только смогу обязательно пошлю код и объясню подробнее.
Desdechado (2006-02-05 15:45:00) [36]> Данные структурированы
вот это самое интересное и самое неосвещенное место в вопросе.
и кода нет
гадаем дальше?
tesseract (2006-02-05 15:43:00) [37]tatiana - Использовать ReadBuffer, а файл открывать, как бинарный с собственным разбором CR/LF.
Gero (2006-02-05 03:05:00) [38]TStringList работает достаточно быстро.
PAVIA (2006-02-05 02:56:00) [39]Чтобы было быстро нужно загрузить файл в памить и там его разбирать. Проще всего через потоки TStream +F1.
Desdechado (2006-02-04 22:51:00) [40]написать быструю процедуру