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

Вниз

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

 
Новенький   (2003-06-27 03:19) [0]

Подскажите как прочитать из файла определенные строки,допустим с пятой по восьмую?


 
Спрашивающий_   (2003-06-27 06:46) [1]

НЕ уточнен тип файла
Например для текстового
procedure TForm1.Button1Click(Sender: TObject);
var
F: TextFile;
S,S1:String;
SL:TStringList;
I:Integer;
begin
S1:= FilenameEdit1.FileName;//путь и имя файла
SL:= TStringList.Create;
AssignFile(F,S1);
If not FileExists(S1) Then
begin
ShowMessage("Files not exists.") ;
Exit;
end;
Reset(F);
try
I:=1;
while not EOF(F) do
begin
Readln(F,S);
If I in [5..8] Then
begin

SL.Add(S);
end;
Inc(I);
If I=9 Then BREAK;
end;
finally
CloseFile(F);
end;
Memo1.Text:=SL.Text;
end;


 
Palladin   (2003-06-27 07:59) [2]


procedure ReadLinesTo(p_strFileName:string;p_SL:TStringList;p_nFrom,p_nTo:integer);
var
f:textfile;
i:integer;
s:string;
begin
assignfile(f,p_strFileName);
reset(f);
try
for i:=1 to p_nFrom do readln(s);
for i:=p_nFrom+1 to p_nTo do
begin
readln(f,s);
p_SL.Add(s);
end;
finally
closefile(f);
end;
end;


 
FoxBox   (2003-06-27 12:01) [3]

var
FileName:String;
FileStrings:TStrings;

begin
...
{Определить FileName}
...
FileStrings:=TStrings.Create;
FileStrings.LoadFromFile(FileName);
...
{берешь нужные тебе строки}
a1:=FileStrings[8]; // нумерация начинается с нуля (напоминаю)
a2:=FileStrings[12]; // это 13-я строка в файле
a3:=FileStrings[20]; // это 21-я строка
...
if FileStrings.Count>150 then
a1:=FileStrings[150]; // это 151-я строка
...
FileStrings.free;
end;


 
Dennis S   (2003-06-27 12:01) [4]

Более простой вариант:
кладешь на форму Memo1, делаешь ему Visible := False

Далее на какое-либо событие:
Memo1.Clear; //На всякий случай
Memo1.Lines.LoadFromFile("C:\твой_файл.txt");
For a := 5 to 8 do begin
S := Memo1.Lines[a].Text; // Или просто Memo1.Lines[a] (не помню, заклинило... ;-) )
......
И делаешь с S(которая у тебя String с нужной инфо), что тебе надо...
......
end;



 
FoxBox   (2003-06-27 12:09) [5]

>>Dennis S
Те же яйца, только в профиль. И смысл
целый компонент держать на форме?


 
Anatoly Podgoretsky   (2003-06-27 12:19) [6]

Нет не теже, а гораздо крупнее, пусть попробует это сделать скажем на 100 мегабайтном файле.


 
FoxBox   (2003-06-27 12:35) [7]

>> Anatoly Podgoretsky
Механизм тот же, в основе лежит использование
типа TStrings (TStringList), поэтому
что Memo.Lines, что собственный экемляр класса
TStrings - ограничения одни и те же.
А текст с количеством строк более 2 миллиардов
- это надо постараться такой текст залить
(разве что "Войну и Мир")


 
Anatoly Podgoretsky   (2003-06-27 12:42) [8]

Нет механизм не тотже, придется все сначала залить в память, с многократным выделением памяти и размером примерно 3n, затем скопировать эти 6 строк, ну это уже ерунда по времени и ресурсам, затем вернуть память. В тоже время для ReadLn только память для максимально длине одной из 8 строк. Да человек не успее отпусть клавишу Старт, как будет все сделано, а с Memo1.Lines.LoadFromFile он успеет кофе выпить, приготовить яичницу и даже поспать немного. Ну я думаю он раньше нажмет Reset.


 
FoxBox   (2003-06-27 12:48) [9]


> Anatoly Podgoretsky

Не вопрос... согласен, выбирать - дело чела.
Пусть сам определит, что ему больше надо.
P.S. Согласен только в данной постановке:
Есть большой файл, надо считать первые несколько
строк, а как быть с файлом, у которого нужно
читать последние строки? А по поводу
загрузки - в процедуре LoadFromFile используется
буферная загрузка - файл сразу весь зальется за
один присест. Вот и разберись, что будет быстрее
работать: несколько ReadLn"ов или один GetMemory
и один LoadtoBuffer.


 
Anatoly Podgoretsky   (2003-06-27 12:53) [10]

Для этого будет отдельная ветка, эта по с 5 по 8, точнее их уже было несколько, недавно. Но точно также не LoadFromFile.
Разбирать повторно не вижу смысла, постоянно приходится работать с большими файлами, от 100 до 250 мегабайт.


 
Serginio   (2003-06-27 12:59) [11]

FoxBox правильно сначала зальетсы в Стрим а потом начинает парсится. Работа с файлами аналогична работы с буферм. Сначала информация закачивается в буффер парсится при достижении конца буффера если нужно сохраняются хвосты и так до конца файла или его начала или до достижения определенного условия. Примеры ассинхронный прием передача данных через кольцевые буфферы.
А ломовые методы не всегда вообще пригодны.


 
FoxBox   (2003-06-27 13:38) [12]


> Anatoly Podgoretsky


Итак, после всех экспериментов...
пробежаться по файлу объемом 173 мега
с кол-вом строк 804712
с помощью LoadFromFile - 1 сек,
с помощью ReadLn - 4 сек.

г-н Погорельский, делай выводы...
Для эксперимента, могу текстовый файл прислать...
Оба подхода не сильно зависят от типа машины.
Идет первичная считка с диска. Единственная сложность:
на старых машинах с оперативкой 64 мега и меньше
предпочтительнее использовать readln (итак нет памяти,
а хранить 170 мега хлама не есть хорошо).
У меня 4-й пень, 256 метров на борту диски IDE

Это статистика, а програмер пусть сам заботится,
какой алгоритм круче...


 
Serginio   (2003-06-27 14:09) [13]

2(FoxBox) Обрати внимание на исходники ReadLine
и структуры
TTextBuf = array[0..127] of Char;

TTextRec = packed record (* must match the size the compiler generates: 460 bytes *)
Handle: Integer; (* must overlay with TFileRec *)
............................................
BufSize: Cardinal;
BufPos: Cardinal;
BufEnd: Cardinal;
BufPtr: PChar;
...........................................
Buffer: TTextBuf;
end;

Если буффер сделаьб достаточно большим и организовать работу аналогичную ReadLine, то этот способ буде намного эффективнее в любом случае, а при условии "с пятой по восьмую?" Вообще единственно приемлемым


 
FoxBox   (2003-06-27 14:23) [14]

Да, есть где развернуться... ОК...
Комментарии. Одно время в бытность паскаля
была функция assign. А в дельфях как она
теперь называется? assignfile
Увы, модули пришлось переписывать при переходе
на дельфу. С тех пор я и не люблю работу с
файлами.
Также был object стал class


 
Serginio   (2003-06-27 14:36) [15]

2(FoxBox) Я уже забыл когда использовал Readln (тем более для коротких строк) FileStream вполне хватает. Речь идет об эффективных приемах решения задач. В свое время для ДВК-2 твой подход просто не проходил бы. А сколько эффективных алгоритмов существует, но заменяются простыми ломовыми методами. А это по моему не ведет к прогрессу.


 
FoxBox   (2003-06-27 14:41) [16]

;->


 
VMcL   (2003-06-27 15:26) [17]

>FoxBox (27.06.03 12:48)
>а как быть с файлом, у которого нужно читать последние строки?

Не пробовал в плане быстродействия, но можно поюзать такой вариант:

FS := FileSize(F) - 1;
for I := FS downto FS - NumberOfBytes + 1 do
begin
Seek(F, I);
// ждём символа(ов) перевода строки и накапливаем строку
// ...
end;


Можно также оптимизировать, читая не по одному байту, а блоками по N КБайт.


 
Anatoly Podgoretsky   (2003-06-27 15:28) [18]

И получаем пустую строку


 
FoxBox   (2003-06-27 15:35) [19]

Вы представляете себе?
Плевый алгоритм, а реализаций наплодили...
Читать слева, читать справа, читать с конца
и середины... Еще нехватает читать данные
хрен знает как... Ну народ! Зачем усложнять
жизнь в первую очередь себе? Вы что? Гении
в разработке кода и не делаете ошибок?
Ведь чем больше исходник, тем выше вероятность
появления бага. Зачем это нужно? Если игра идет
на миллисекунды, нужно упрощать код, а не
плодить "если-тосли". Смысл?



 
Anatoly Podgoretsky   (2003-06-27 15:40) [20]

FoxBox (27.06.03 13:38)
Тоже самое
LoadFromFile - 10 минут, ReadLn - 12 секунд.
Это что же у тебя за винчестер такой, что свыше 173 мегабайт в секунд, да и время там идет совсен на другое, на выделение памяти, на парсинг строк в Мемо и прочее.

У тебя наверно не чисто текстовый файл, а скажем с символами #0


 
Serginio   (2003-06-27 15:48) [21]

2(Anatoly Podgoretsky © (27.06.03 15:40))
Такие скорости вполне реальны на чтение файлов на винтах 7500 об (не говоря о Raid массивах и скази). Выделение памяти единовременно тоже не проблема. А на современных машинах и память побыстрее и шины и кэши.
Очень интересно при этом смотреть как на скорость БД. Вот уж где применяются не эффективные алгоритмы.


 
Anatoly Podgoretsky   (2003-06-27 15:55) [22]

У меня 650, 512 RAM, диски 7200 и 10000 об/мин, Р3 ATA V, DMA 100
не Р4 конечно, поэтому не 4 секунды, а 12
Про RAID не скажу, может там и удастя получить свыше 200 мб/сек, но разбиение на строки и встраивание их в МЕМО это длительная операяция, у меня правда измерения шли на TRichEdit из за лимита на Win9x


 
FoxBox   (2003-06-27 16:06) [23]


> Anatoly Podgoretsky

Нужно читать не в Мемо, а в
TStringList, т.к. после загрузки
файла компонент мемо начинает прорисовывать
всю эту хрень или какие-то другие операции
делать. В-общем, эксперимент не в чистом виде.
А чтобы совсем было хорошо, поставьте
для Memo visible в TRUE - время сильно изменится?

s:tstringlist;
t:tdatetime;
ss:string;
f:textfile;
begin
{один метод}
t:=now;
s:=tstringlist.create;
s.loadfromfile("d:\123.txt");
edit2.text:=inttostr(s.count)+"-"+s[s.count-1];
s.free;
showmessage(timetostr(now-t));

{другой метод}
t:=now;
assignfile(f,"d:\123.txt");
reset(f);
while not eof(f) do
readln(f,ss);
closefile(f);
showmessage(timetostr(now-t));


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


 
Serginio   (2003-06-27 16:07) [24]

У меня Athlon XP 2400+, память 750 МБ РС 3200, частота шины 133 и Винт Сигейт St3820021А (7500 оборотов) карта MSI NVIDIA
Считывает большими кусками в районе 200 мб/сек.
Дома поробую со TStringList попробовать. (МЕМО ,TRichEdit для других целей).
В любом случае я ярый противник лобовых (крайне не эффективных) приемов.


 
Serginio   (2003-06-27 16:15) [25]

2(FoxBox) Эх представляешь себе некую БД при работе твоими методами. Есть некоторые приемы хранения и редактирования текста больших объемов через двухнаправленные списки. Где удаление и вставка не столь критичны по ресурсам. Есть их более большие разновидности где еще и сама строка может разбиваться на списки.
В БД применяются MEMO поля итд. Для решения каждой задачи нужен свой подход.


 
FoxBox   (2003-06-27 16:16) [26]


> Serginio

Попробуй. Возьми даже мой исходник - не
мучайся сам. Интересен будет результат.
Но не думаю, чтобы были какие-то отличия.
То, что я предлагаю, в большей степени
будет успешно работать на крутнявых компах,
а ReadLn пригоден для совсем древних.


 
Anatoly Podgoretsky   (2003-06-27 16:18) [27]

FoxBox (27.06.03 16:06)
Минуточку, у меня было конкретное возражение именно по поводу МЕМО а не TStringList, со TStringList совсем другая раскладка по времени.
Со TStringList у меня примерно одинаковое время, точнее сильно зависит от зарактера информации в файле, для упрощения будем считать почти одинаковое.

Serginio (27.06.03 16:07)
Если будешь пробовать, то пробуй оба варианта и на файлах большого размера, желательно значительно больше чем размер ОЗУ


 
FoxBox   (2003-06-27 16:22) [28]

А я про что говорил? именно про TStringList,
но не про Memo.

А по поводу пробования...
ессно надо оба (нафига один? в чем тогда смысл?)

Но у Serginio крутнявая тачка, TStringList выиграет!!!


 
MMF   (2003-06-27 16:30) [29]

Если уж надо сделать чем быстрее, тем лучше, и при этом управлять направлением чтения (скажем прочитать десять последних строк из миллиона или наоборот) я сделал бы примерно так:
Function GetStrFromFile( FileName: string; FromStr, ToStr: Integer;
ModeForward: boolean): TStringList;
var
FFileHandle: THandle;
PData: PChar;
FMapHandle: THandle;
FFileSize, StringCnt: Integer;
const
ErrFileOpen="Ошибка открытия";
ErrCreateMap="Ошибка отображения в память";
begin
Result:=TStringList.Create();
StringCnt:=0; //счетчик строк
FFileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
if FFileHandle = INVALID_HANDLE_VALUE then exception.Create(ErrFileOpen);
FFileSize := GetFileSize(FFileHandle, nil);
FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY, 0, FFileSize,nil);
if FMapHandle = 0 then
begin
CloseHandle(FFileHandle);
exception.Create(ErrCreateMap);
end;
CloseHandle(FFileHandle);
PData := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, FFileSize);
if PData = nil then
begin
CloseHandle(FMapHandle);
exception.Create(ErrCreateMap);
end;
//в зависимости от направления чтения файла заполняем Result строками из PData по условию попадания в диапазон
* * * * *
if PData <> nil then
begin
UnmapViewOfFile(PData);
CloseHandle(FMapHandle);
PData := nil;
end;
end;


 
Serginio   (2003-06-27 16:30) [30]

2(FoxBox (27.06.03 16:16)) Во первых ты хоть читаешь, что я предлагаю. А именно считывать в буффер большого объема размером с КЭШ буффер процессора и парсить его последовательно с перегрузкой. Ничего в этом алгоритме нет такого уж навороченного, но намного эффективнее.
А ReadLn я никогда в жизни использовать не буду. Архаика понимаете ли.

2(Anatoly Podgoretsky © (27.06.03 16:18))
А есть ли смысл. Если и так понятно где черное а где белое.


 
Serginio   (2003-06-27 16:34) [31]

2(MMF) Ну ты любитель FileMapping ов. Не забыл еще обыкновенный TFileStream ???
Помог тебе TStreamAdapter ??? Сам ни разу не пользовался.


 
FoxBox   (2003-06-27 16:37) [32]

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

>MMF
Возможно, в борланде и сделали подобную
реализацию метода LoadFromFile.

Я не смотрел исходники, надо будет поковыряться...
А так, чертовски забавно было... жаль автор не увидит
всех высказываний...


 
Anatoly Podgoretsky   (2003-06-27 16:40) [33]

А зачем тогда мерить?
Насчет архаики ты не совсем прав, попробуй реализовать например

ReadLn(F,Real,Integer,Boolean,String);

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

Эта псевдо процедура заточена именно на текстовые файлы и с минимальными требованиями к ресурсам, например безразмерные файл из потока.


 
MMF   (2003-06-27 16:42) [34]

>Serginio (27.06.03 16:34)
Просто я реально столкнулся при анализе журнала регистрации 1С с необходимостью чтения строк с конца файла. Другого способа, кроме как отобразить в память, в голову не пришло. До TStreamAdapter руки еще не дошли, :-(


 
Anatoly Podgoretsky   (2003-06-27 16:49) [35]

Я к тому что рано его хоронить, использовать там где он лучше, а не из религии.


 
Serginio   (2003-06-27 16:54) [36]

2(Anatoly Podgoretsky © (27.06.03 16:40))
в Serginio (27.06.03 14:09) я привел пример неэффективности Readln именно из маленькой величины буффера. Да и создан он был еще когда не было понятий длинных строк. Создать свой современный аналог последовательного чтения строк из файла с использованием большого буффера в любом направлении тривиальная задача. Не более чем тренировка для ума.
2(MMF) Честно говоря мало использовал FileMapping но видя как работают некоторые БД от M$ (которые его используют пока памяти хватает без перегрузки страниц) по моему ничем от LoadFromFile мало отличается. Но это при условии FileMapping всего файла. Но у него есть замечательная вещь как загрузка и выгрузка и сохранение нужных страниц.


 
rkostya   (2003-06-27 21:27) [37]

2 Serginio (27.06.03 16:07)
"У меня Athlon XP 2400+, память 750 МБ РС 3200, частота шины 133 и Винт Сигейт St3820021А (7500 оборотов) карта MSI NVIDIA
Считывает большими кусками в районе 200 мб/сек."
Ты слишком доверчив :) Это в характеристиках винта пишут, что максимальная(!) скорость обмена достигает 200 мб/с. Это случается только когда твои данные ФИЗИЧЕСКИ записаны в последовательно чередующихся секторах. Реально такие диски дают ~60 мб/с. Если не веришь, возми файл размером ~600М и скопируй(а не мувни) в другой каталог. Тогда и посмотришь, уложится ли он в 6 с. Я думаю, получится ~30с. :)
P.S.
Ради интереса сходил на www.seagate.com :)
Ты, наверное, имел в виду ST380021А (7200 RPM) :) Для него максимальная скорость обмена 100 М/с, средняя - 21-41 М/с.
P.P.S
Так что, 173М могли считаться за 1с только в том случае, если уже сидели в дисковом кэше, т.е., считывались не в первый раз.

2FoxBox (27.06.03 13:38)
"Итак, после всех экспериментов...
пробежаться по файлу объемом 173 мега
с кол-вом строк 804712
с помощью LoadFromFile - 1 сек,
с помощью ReadLn - 4 сек.
г-н Погорельский, делай выводы..."

Результаты похожи на правду только если сначала запустить тест ReadLn, а затем LoadFromFile. Если протестироваться в обратном порядке, результаты будут противоположные.
г-н ЛисийЯщик, делай выводы :)



 
Tano   (2003-06-28 20:48) [38]

8-(0) no comments...


 
Serginio   (2003-06-30 13:58) [39]

Всетаки провел я тесты.
Специально были сделаны объекты для последовательного чтения текстовых файлов как в прямом так и в обратном направлении TTextReader и TTextBackReader использующие кольцевой буффер размером 64 кб с ограничением на длину строки 64 кб - 3 байта.
Сразу предупреждаю, что не протестированы на все граничные условия.

Исходники и тест на
http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019

Следует оговорить, что тест проходил на уже кэшируемом файле.
Не удивляйтесь скорости чтения 0.375 сек.


Размер тестируемого файла 148 888 907 бйт
Количество строк 10 000 001
============== Тест СтрингЛист============================
Использование TstringList
StringList Загрузка парсинг и выделение строк=9
Время освобождения StringList =1.594
Проверка TTextReader=6.657
Проверка TTextBackReader=8.562
==========================================
Использование TTextReader
Загрузка парсинг и выделение строк=3.391
Загрузка и парсинг без выделения строк=1.859

==========================================
Использование TTextBackReader
Загрузка парсинг и выделение строк=3.157
Загрузка и парсинг без выделения строк=1.828
==========================================
Использование старого Readln
Чтение Выделением строк=4.453
Чтение без Выделения строк=2.484
==========================================

Загрузка всего файла в память и парсинг аналогично TstringList
Выделение памяти=0.25
Загрузка всего файла в память =0.375
Парсинг =1.953
Итого =2.578

Сдесь сразу следует оговорить, что специально для TstringList был опреден Cappasity
равный количеству строк в текстовом файле. Иначе результаты разнились бы в разы из-за
перераспределения непрерывной памяти (Пример в директории MyMemmoryStream прекрасно
показывает недостатки использования непрерывной памяти большого объема ).
Кроме всего почего надо учесть, что на каждую не пустую строку дополнительно выделяется
13 байт (TUsed, Количество Ссылок, длина строки,#0) и TstringList выделяет 8 байт
(ссылка на строку и на объект) итого дополнительно 21 байт.
При 10 милионах записей это 210 мб памяти. И еще 148 888 907 бйт в буффере
и 128 888 907 на строки (за минусом #13#10).
Даже при моих ресурсах (750 мб-250 мб на видеопамять) использование файла подкачки
неизбежно.

Разница в скорости TTextReader и TTextBackReader обусловлена на отсутствии сравнения в
TTextBackReader сравнения на #0 и работой Менеджера Памяти, так как TTextBackReader
сначала считывает строки большего размера.

Разница между парсингом непрерывной памятью и буфером TTextReader и TTextBackReader в использовании кэша процессора

Незнание конкретной реализации FileText оставляю без комментариев.
В любом случае использования TstringList для чтения строк не опрадано.


 
Serginio   (2003-07-01 13:56) [40]

Может кому интересно. Провел тот же тест для .NET (правда только парсинг и выделение строк, не опытный я еще С# -ист, да и непривычная среда VS .Net) и был приятно удивлен. Победителем вышел NET правда всего где то на 7% но сам факт ответ скептикам NET. Будущее за NET.



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

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

Наверх





Память: 0.57 MB
Время: 0.016 c
3-44599
Brain Force
2003-06-20 18:26
2003.07.14
Народ, помогите ламеру с отчетами....


3-44544
div
2003-06-19 13:55
2003.07.14
Вылетает


4-44944
MW Programs
2003-05-13 16:37
2003.07.14
Message LBM_


14-44854
Думкин
2003-06-26 06:31
2003.07.14
Родственники на работе


6-44783
altarasjuk
2003-05-07 14:04
2003.07.14
peer-to-peer чат.





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