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

Вниз

Быстрое чтение файла   Найти похожие ветки 

 
Кастуся   (2004-06-21 22:46) [0]

мастера, хелп!
обрабатываю файл "дедовским" методом: построчно читаю данные и со строкой делаю все необходимое.
Но не устраивает скорость. На 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?
В общем как тут быть. Дело срочное, хелп плиз!!!


 
Anatoly Podgoretsky ©   (2004-06-21 23:15) [1]

Если не ошибаюсь, то тут два раза чтение из файла того же самого содержимого. Посмотри в сторону текстовыъ файлов и ReadLn


 
DrPass ©   (2004-06-21 23:19) [2]


> но что такое FindCR?

Наверняка какая-то самописная функция, которая ищет среди последовательности символов знак возврата каретки.
А после этого файл считывается во второй раз...


 
RealRascal ©   (2004-06-21 23:21) [3]

Может поможет txtfile:TStringlist;
Чтобы загрузить используй Tstringlist.LoadFromFile()
Потом обращайся к нужной строчке txtfile[i]


 
Кастуся   (2004-06-22 08:40) [4]


> Anatoly Podgoretsky ©

Первоначально и смотрю в сторону ReadLn, но можно быстрее? через TFIleStream или BlockRead?


 
Anatoly Podgoretsky ©   (2004-06-22 08:50) [5]

Кастуся   (22.06.04 08:40) [4]
Выигрываешь немного в скорости чтения, проигрываешь в обработке, придется самому разбирать буфер на строки и не дай бог на составляющии. Текстовые файлы обеспечивают отличный механизм разборки файла и преобразования из буквочек в типы. Но всему свое место, твоя задача нам неизвестна.

Могу предложить, если у тебя текстовый файл, то загнать его целиком в строковую переменную и ее присвоить TStringList.Text возможно это будет быстрее, а то и сразу загрузить в TStringList, по скорости можно выиграть немного, по сравнению с текстовыми файлам, но за счет проигрыша по памяти. Но это хорошо только для текста.


 
Кастуся   (2004-06-22 09:44) [6]

С TStringLIst я пробовал - медленнее чем просто readln Использую SetTextBuf Я думаю это помогает?


 
Serginio666   (2004-06-22 14:10) [7]

Посмотри
http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019
Тест на чтения текстовых файлов различными способами. Также исходники объектов для последовательного чтения текстовых файлов
как в прямом так и в обратном направлении TTextReader и TTextBackReader использующие кольцевой буффер размером 64 кб с ограничением на длину строки 64 кб - 3 байта.


 
BFG9k   (2004-06-22 14:45) [8]

Паскаль в гробу перевернется после всего этого. CreateFile,SetFilePointer,FileRead,FileWrite,CloseHandle . API функции - лучший друг Delphi-программиста.


 
Mim1 ©   (2004-06-22 17:38) [9]


>  [8] BFG9k   (22.06.04 14:45)
> Паскаль в гробу перевернется после всего этого. CreateFile,SetFilePointer,FileRead,FileWrite,CloseHandle
> . API функции - лучший друг Delphi-программиста.


Ну ну :), я бы сказал лучший враг. Но это субьективно.
Если смотрите в будующее о api лучше забыть.
API приходят и уходят, ЯП остается :)


 
Кастуся   (2004-06-22 17:55) [10]

Понимете, вся штука вот в чем: в текстовом файле находится строка-идентификатор, после чего ещё пару строк считывается и они обрабатываются. Т.е. вся фишка в том, чтобы как можно быстрее найти эту заветную строку. Таких блоков может быть много в файле.
Вот смотрел ещё:
http://delphiworld.narod.ru/base/search_text_in_text_file.html
но не могу разобраться. может подскажите?


 
Anatoly Podgoretsky ©   (2004-06-22 17:59) [11]

Не сортированый список, только перебором


 
Кастуся   (2004-06-22 18:25) [12]

серьезно?


 
Amoeba ©   (2004-06-22 18:31) [13]


> Кастуся   (22.06.04 18:25) [12]
> серьезно?

Совершенно серьезно.


 
panov ©   (2004-06-22 18:31) [14]

>Кастуся   (22.06.04 18:25) [12]
Серьезно.


 
GrayFace ©   (2004-06-22 18:37) [15]

Искать строку в файле действительно лучше не дедовским способом. Если файл меньше 50 MB (для малых оперативок еще меньше), то можно грузить весь в строку(FileRead или BlockRead) и искать в ней стандартными способами. Если файл огромен, то прийдется немного помучаться.


 
Serginio666   (2004-06-22 19:13) [16]

>>GrayFace ©
Немного ошибаешься. Лучше грузить в блок соизмеримый с размером кэша первого уровня. В отличие от твоего способа, все данные будут лежать в кэше и проход по ним будет быстрее. Что и доказывают тесты в Serginio666   (22.06.04 14:10) [7]


 
GrayFace ©   (2004-06-22 19:20) [17]

А что такое кэш первого уровня?


 
Jeer ©   (2004-06-22 19:33) [18]

Который в процессоре и ближе к нему чем к ОЗУ.


 
Кастуся   (2004-06-23 09:08) [19]

короче вот что я тет выяснил
путаю я вас тут
львиную долю времени загрузки файла как раз занимет его одновременная обработка!
Может можно как-то подгружать функции в память, чтобы их быстрее вызывать? Вот может посмотрите как можно вот этот код оптимизировать:
AssignFile(F,FileName);
SetTextBuf(f,buf);
Reset(f);
Ln:=FileSize(F);
while not eof(F) do
 begin
  Readln(F,w);
  if Trim(w)="TC" then
   begin
    Readln(F,W);
    rst:=DelSpaces(W);
    I:=0;
    repeat
     inc(i);
     Readln(F,W);
     w0:=DelSpaces(W);
     Bad:=(Length(w0)<>32);
     if not Bad then
      Bad:=not (LastDelimiter(HexSt,AnsiLowerCase(w0))=32);
     k:=0;
     if not Bad then
      repeat
       inc(k);
       REAPage.Matr[i,k]:=w0[k];
      until (k=32);
    until (i=8) or Bad;

    if not Bad then
     begin
      if not Result then Result:=True;
      Inc(DataTables[0].CurLen);
      for I:=1 to MaxCol do
       SetLength(DataTables[0].DataArr[I],DataTables[0].CurLen);
      REAInfo.REAPage.ProcessMatr(rst);
     end;
   end;
  Cps:=FilePos(F);
  if Ln=0 then MainForm.StBar.Panels.Items[2].GaugeAttrs.Position:=100
   else MainForm.StBar.Panels.Items[2].GaugeAttrs.Position:=Round((Cps/Ln)*100);
 end;
MainForm.StBar.Panels.Items[1].Text:="";
CloseFile(F);


 
Anatoly Podgoretsky ©   (2004-06-23 11:31) [20]

Кастуся   (23.06.04 09:08) [19]
Функции и так в памяти, всегда, Дельфи не интерпритатор.


 
Кастуся   (2004-06-23 12:33) [21]

а так можно как-нибудь увеличить скорость ?


 
Sandman25 ©   (2004-06-23 12:39) [22]

>а так можно как-нибудь увеличить скорость ?

Не использовать Trim, DelSpaces, LastDelimiter, AnsiLowerCase
Это      repeat
      inc(k);
      REAPage.Matr[i,k]:=w0[k];
     until (k=32);
заменить на 1 команду CopyMemory


 
Кастуся   (2004-06-23 15:47) [23]

Sandman25 ©   (23.06.04 12:39) [22]

знац-ца так
AnsiLowerCase отключил
Это      repeat
     inc(k);
     REAPage.Matr[i,k]:=w0[k];
    until (k=32);
заменил на 1 команду CopyMemory вот как:
MoveMemory(@REAPage.Matr[i],@w0[1],32);

Скорость впечатляет: файл в 23.8Мб обрабатывает за 46 сек, когда до изменений было 56! Это на моем-то Celerone-533+SDRam-64Mb, а для кого это делается вообще P-I-133 + SD-RAM 16Mb! Так что там разница будет раза в 2 больше. Хотя там такие большие файлы не обрабатывают Макс - ~5Мб
HexSt:="0"+"1"+"2"+"3"+"4"+"5"+"6"+"7"+"8"+"9"+"a"+"b"+"c"+"d"+"e"+"f";

w0:=DelSpaces(W);
Bad:=(Length(w0)<>32);
if not Bad then Bad:=not (LastDelimiter(HexSt,w0)=32);


 
Sandman25 ©   (2004-06-23 16:03) [24]

LastDelimiter(HexSt,w0)=32
эквивалентно
(Length(w0)=32) and (w0[32] in ["0".."9","a".."f"])


 
Кастуся   (2004-06-23 16:14) [25]

мне надо чтобы вся строка состояла из ["0".."9","a".."f"] а не только последняя "буква"(w0[32])! Или я что-то не понимаю?


 
Sandman25 ©   (2004-06-23 16:18) [26]

Почитайте описание LastDelimiter.
Если захотите проверять каждый символ, скорость чтения файла упадет примерно в 30 раз....


 
Кастуся   (2004-06-23 17:03) [27]

Sandman25 ©   (23.06.04 16:18) [26]
а как тогда быть?


 
Sandman25 ©   (2004-06-23 17:04) [28]

[27] Кастуся   (23.06.04 17:03)

От задачи зависит. Если это лабораторная, а не программа управления ядерным реактором, то можно не проверять.


 
Кастуся   (2004-06-23 17:51) [29]


> Sandman25 ©   (23.06.04 16:18) [26]


Знаешь ли ты английский язык?
Нет?
Вот чт написано в хелпе:

function LastDelimiter(const Delimiters, S: string): Integer;

Returns the byte index in S of the last character that matches any character in the Delimiters AnsiString.

Call LastDelimiter to locate the last delimiter in S. For example, the line

MyIndex := LastDelimiter("\.:","c:\filename.ext");

sets MyIndex to 12.

Перевожу:

function LastDelimiter(const Delimiters, S: string): Integer;

Возвращает индекс последнего символа строки S, который совпадает с любым из символов в строке Delimiters.

Используйте LastDelimiter для определения позиции последнего совпадающего символа. Например, строка

MyIndex := LastDelimiter("\.:","c:\filename.ext");

устанавливает значение MyIndex равным 12.

Даже пример есть, хоть по примеру можно догодацца-то! No comments...


 
Кастуся   (2004-06-23 17:52) [30]


> а не программа управления ядерным реактором,

а если именно эта программа?


 
Romkin ©   (2004-06-23 18:09) [31]

ЭЭЭ. А нельзя ли получить формальную постановку? А то с кодом как-то разбираться не хочется.
Насколько я понял, тебе парсинг строки сделать надо? Это в общем случае решается конечным автоматом, который просто считывает весь файл непрерывным потоком. Однократно.
Как правило, это быстрее всего. А вот какой автомат должен быть - это надо выбирать...
http://rsdn.ru/article/alg/statemachine.xml


 
Кастуся   (2004-06-23 19:21) [32]

Так, вот конкретно. Требуется две вещи:
1) есть ли втроенная процедура удаления из строки всех пробелов? Если нет, то как это можно наибыстрее реализовать? Моя реализация:
function DelSpaces(S:String):String;
var
I:Integer;
begin
Result:="";
for I:=1 to Length(S) do
 if S[I]<>" " then Result:=Result+S[I];
end;

2) нужна процедура проверки валидности символов в строке, а точнее надо проверить, являются ли все символы в строке "шестнадцатеричными", т.е. принадлежат ["0".."9","a".."f"]. Опять наибыстрым способом. Моя реализация:
Bad:=not (LastDelimiter(HexSt,w0)=32);


 
Romkin ©   (2004-06-23 19:28) [33]

Кастуся  (23.06.04 19:21) [32]
1. Фиии.
StringReplace тоже не быстро...

function DelSpaces(const S: String):String;
var
 I, k, len:Integer;
begin
 len := Length(S);
 SetLength(Result, len);
 k := 0;
 for I := 1 to len do
   if S[I]<>" " then
   begin
     inc(k);
     Result[k] := S[I];
   end;
 SetLength(Result, k);
end;

Думаю, сойдет. Можно и быстрее, но не намного.
2. Если строка не более 16 символов, то
N := IntToStr("$"+S);
Преобразует, если не прет - даст исключение


 
Romkin ©   (2004-06-23 19:41) [34]

тьфу, StrToInt("$"+S) разумеется


 
Anatoly Podgoretsky ©   (2004-06-23 20:13) [35]

StrToInt64


 
Anatoly Podgoretsky ©   (2004-06-23 20:25) [36]

Кастуся   (23.06.04 19:21) [32]
Алгоритм очень неэффективный, постоянное перераспределение памяти, алгоритм приведенный Ромкином при определенных условиях даст ускорение на порядки, например если обрабатывать весь громадный файл на один проход, но не на один порядок быстрее. Чем длиннее строка, тем быстрее, зависимость не линейная.


 
Кастуся   (2004-06-23 22:28) [37]

> Anatoly Podgoretsky ©   (23.06.04 20:25) [36]

> Алгоритм очень неэффективный, постоянное перераспределение
> памяти

Это ты про мой?


> алгоритм приведенный Ромкином при определенных условиях
> даст ускорение на порядки

алгоритм удаления пробелов из строки? и при каких условиях

> обрабатывать весь громадный файл на один проход

т.е.?


 
Кастуся   (2004-06-23 22:55) [38]


> Romkin ©   (23.06.04 19:41) [34]


> Можно и быстрее, но не намного.

Говори как. Для меня очень важна скорость.


> N := StrToInt64("$"+S);

строка 32-х символьная
и при попытке конвертации первой же такой строки возникает ошибка "not a valid integer value" Что делать?
Вот пример строки:
000E190E131002001104294188601618


 
Anatoly Podgoretsky ©   (2004-06-23 22:58) [39]

Для конвертации такой строки нужен Int128


 
Fay ©   (2004-06-24 06:38) [40]

2Кастуся   (23.06.04 22:28) [37]
Твой способ удаления пробелов в строке ДИКО медленный.
Сравни с [33] на 10000 символах.



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

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

Наверх





Память: 0.56 MB
Время: 0.033 c
3-1086952853
Ven
2004-06-11 15:20
2004.07.11
Как увеличить скорость подключения к сетевой БД


4-1086168939
panov
2004-06-02 13:35
2004.07.11
HDC, использование в OnPaint


1-1088288639
TGrey
2004-06-27 02:23
2004.07.11
Как сохранить TList в файле


11-1075844882
Ciber SLasH
2004-02-04 00:48
2004.07.11
TKOLTabControl


3-1087452298
alsov
2004-06-17 10:04
2004.07.11
Запрос в виде цикла





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский