Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.07.28;
Скачать: [xml.tar.bz2];

Вниз

Чтение файла   Найти похожие ветки 

 
Sandman25   (2003-07-15 15:42) [0]

Добрый день.
Подскажите, пожалуйста, алгоритм для чтения файла.
В файле находятся данные (и управляющие последовательности) для экспорта в Excel, разделенные неким символом (например, "|").
Как наиболее эффективно считывать данные из файла до первого разделителя, при этом игнорируя концы строк?
Пока делаю так:

const FieldsDelimiter = "|";

function ReadFromFile(var F: File): String;
const
MaxLineLength = 500;
var
Ch: char;
ResultLength: integer;
BytesReadCount: integer;
begin
SetLength(Result, MaxLineLength);
ResultLength := 0;
repeat
BlockRead(F, Ch, 1, BytesReadCount);
if BytesReadCount > 0 then
begin
case Ch of
#10, #13: continue;
FieldsDelimiter: break;
end;
inc(ResultLength);
Result[ResultLength] := Ch;
end
else
break;
until false;
SetLength(Result, ResultLength);
end;

procedure SendToExcel(FileName: string);
var
F: File;
S: String;
begin
...
try
AssignFile(F, FileName);
Reset(F, 1);
try
S := ReadFromFile(F);
showmessage(S);
...
finally
CloseFile(F);
end;
...
end;


Но мне не нравится, что я читаю всего по одному символу.
Наверное, можно попробовать считывать в буфер большего размера (модульную переменную) и по мере необходимости получать из нее следующее значение. Но стоит ли, или Delphi и так использует неявное буферирование?


 
Тфьу   (2003-07-15 15:47) [1]

Можно использовать ReadLn(FileHandle,AString);


 
Sandman25   (2003-07-15 15:52) [2]

>Можно использовать ReadLn(FileHandle,AString);

Это частный случай буфера большего размера с необходимостью запоминать остаток строки в случае наличия в ней нескольких разделителей. Особенно неприятно получается, если в конце строки нет разделителя, тогда надо объединять несколько строк. Можно ли как-то обойтись без модульных переменных (запоминания контекста между вызовами функции ReadFromFile)?


 
Serginio   (2003-07-15 16:13) [3]

http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019


 
Sandman25   (2003-07-15 16:43) [4]

Serginio

Не качается. Вы имели ввиду TTextReader? Спасибо, я уже решил оставить пока все так, как есть. Потом если будет время, исправлю.


 
Anatoly Podgoretsky   (2003-07-15 16:49) [5]

Если ты воспользуешься следующим приемом, то у тебя будет одна длинная строка.

LongStr := "";
While not eof(F) do
begin
WtiteLn(F,S);
LongStr := LongStr + " " + S;
end;

Можно закачать так же в TStringList, тогда у тебя будет одна строка без всяких усилий.


 
Serginio   (2003-07-15 17:00) [6]

Delphi в TextFile использует кольцевой буффер правда размером 128 байт
TTextBuf = array[0..127] of Char;
TTextRec = packed record (* must match the size the compiler generates: 460 bytes *)
Handle: Integer; (* must overlay with TFileRec *)
Mode: Word;
Flags: Word;
BufSize: Cardinal;
BufPos: Cardinal;
BufEnd: Cardinal;
BufPtr: PChar;
OpenFunc: Pointer;
InOutFunc: Pointer;
FlushFunc: Pointer;
CloseFunc: Pointer;
UserData: array[1..32] of Byte;
Name: array[0..259] of Char;
Buffer: TTextBuf;
end;


 
Sandman25   (2003-07-15 17:14) [7]

Anatoly Podgoretsky

Сразу весь файл качать в память я не могу - он может оказаться слишком большим.

Serginio

Спасибо. Наверное, я все-таки воспользуюсь Readln.


 
Anatoly Podgoretsky   (2003-07-15 17:17) [8]

Можно разновидность, ReadLn до первого разделителя и склеивание строки. Все много быстрее посимвольного чтения.


 
Anatoly Podgoretsky   (2003-07-15 17:17) [9]

Просто продумать наиболее оптимальный алгоритм, в зависимости от характера твоих данных.


 
Serginio   (2003-07-15 17:28) [10]

Я не буду настаивать, но алгоритмов с использованием кольцевого буфера очень много. Лучше набить руку на будущее. И в итоге тот же не оптимизированный TTextReader оказывается быстрее чем ReadLn. Тем более когда данные нужно читать с конца.


 
Sandman25   (2003-07-15 17:35) [11]

ОК, всем спасибо. Вроде понял.


 
Sandman25   (2003-07-15 18:05) [12]

Сделал так, должно быть быстрее.

var
F: TextFile;
ReadString: string;

function ReadFromFile: String;
var
DelimiterPos: integer;
LengthReadString: integer;
begin
LengthReadString := Length(ReadString);
if LengthReadString = 0 then
begin
while not Eof(F) do
begin
Readln(F, ReadString);
if Pos(FieldsDelimiter, ReadString) > 0 then
break;
end;
LengthReadString := Length(ReadString);
end;
DelimiterPos := Pos(FieldsDelimiter, ReadString);
Result := Copy(ReadString, 1, DelimiterPos - 1);
if DelimiterPos <> LengthReadString then
Delete(ReadString, 1, DelimiterPos)
else
SetLength(ReadString, 0);
end;


 
Serginio   (2003-07-15 18:30) [13]

Быстрее у тебя не получится так как ты таскаешь данные по буферу (Delete) POS конечно хорошая функция но легче самому пропарсить.


 
Sandman25   (2003-07-15 18:41) [14]

Serginio

Понятно, буду переделывать. Спасибо.


 
Song   (2003-07-15 21:37) [15]

CreateFileMapping, MapViewOfFile()
или TFileStream
100% быстрей будет чем у тебя.
У меня в программе файл 40М загружается в память за 2 сек. Далее всё завит от алгоритма его перебора.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.07.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.006 c
3-91667
Skywalker
2003-07-04 17:25
2003.07.28
Почему не работает запрос?


14-91864
AlexGreG
2003-07-11 08:22
2003.07.28
... Запрос, как много в этом звуке ...


7-91929
RRR
2003-05-19 14:56
2003.07.28
IRDA ...


6-91797
exciter__
2003-05-22 14:31
2003.07.28
Проблема с модемом (определить поднятие трубки)


4-91962
tovSuhov
2003-05-23 13:05
2003.07.28
GetLastError





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский