Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Открытие большого файла [D6, Win95/98, Win2k]


Sherbacov ©   (2003-02-06 23:22:00) 

Уважаемые мастера, помогите в решении проблемы
существует большой тестовой файл 300 мегов, я открываю его (я знаю это не правильно) memo1.lines.loadfromfile("big.txt");и перехожу на строчку последнюю минус 9.
Но очень долго и еще файлы да 150 мегов открывает нормально, а больше с ошибкой.
Помогите.


MBo   (2003-02-07 16:57:00) [1]

Вариант для чтения единственной строки:

function GetNthLineFromEnd(const NumFromEnd:Integer;const FileName:string):string;
var
FileH: THandle;
MapH: THandle;
Size,Count: Integer;
PMap,PB: PByte;
PEnd:PChar;
begin
Assert(FileExists(FileName),"File not found!");
FileH:=FileOpen(FileName, fmOpenReadWrite);
if FileH<>INVALID_HANDLE_VALUE then begin
Size:=GetFileSize(FileH, nil);
MapH:=CreateFileMapping(FileH,nil,PAGE_READONLY,0,Size,nil);
if MapH<>0 then begin
PMap:=MapViewOfFile(MapH,FILE_MAP_READ,0,0,Size);
if PMap<>Nil then begin
PB:=PMap;
inc(PB, Size);
if PB^<>10 then
Count:=1
else
Count:=0;
repeat
Dec(PB);
if PB^=10 then
Inc(Count);
until (Count>NumFromEnd) or (PB=PMAP);
if PB<>PMap then
Inc(PB);
PEnd:=StrScan(PChar(PB),#13);
if PEnd=nil then begin
PEnd:=Pchar(PMap);
Inc(PEnd,Size);
end;
SetString(Result, PChar(PB), PEnd-PB);
UnmapViewOfFile(PMap);
end;
CloseHandle(MapH);
end;
CloseHandle(FileH);
end;
end;


MBo   (2003-02-07 16:40:00) [2]

>Игорь Шевченко
Не юродствуйте, Штирлиц ;)
Покритиковал бы лучше.


Игорь Шевченко   (2003-02-07 16:31:00) [3]

MBo © (07.02.03 16:10)

Уважометр, однако, зашкаливает :-)


MBo   (2003-02-07 16:30:00) [4]

5 последних строк. Надо было аргумент назвать попонятнее ;(


Palladin   (2003-02-07 16:27:00) [5]

2 Song
это номер нужной строки, с конца...


Palladin   (2003-02-07 16:25:00) [6]

ну все :)
больше никогда не буду придиратся к MBo :))
а кстати почему (С), а не "M". Не порядок :)


Song   (2003-02-07 16:19:00) [7]

MBo, где же ты был раньше? -))

Чего-то только я не понял, а что означает параметр 5 ?


MBo   (2003-02-07 16:10:00) [8]

>Игорь Шевченко
Вы хочете MMF-ов? Их есть у меня ;)

procedure GetLastLines(const nstr:Integer;const FileName:string;Lines:TStrings);
var
FileH: THandle;
MapH: THandle;
Size,Count: Integer;
PMap,PB: PByte;
begin
Assert(FileExists(FileName),"File not found!");
Assert(Assigned(Lines),"Where should I write to????");
FileH:=FileOpen(FileName, fmOpenReadWrite);
if FileH<>INVALID_HANDLE_VALUE then begin
Size:=GetFileSize(FileH, nil);
MapH:=CreateFileMapping(FileH,nil,PAGE_READONLY,0,Size,nil);
if MapH<>0 then begin
PMap:=MapViewOfFile(MapH,FILE_MAP_READ,0,0,Size);
if PMap<>Nil then begin
PB:=PMap;
inc(PB, Size);
if PB^<>10 then
Count:=1
else
Count:=0;
repeat
Dec(PB);
if PB^=10 then
Inc(Count);
until (Count>nstr) or (PB=PMAP);
if PB<>PMap then
Inc(PB);
Lines.Text:=PChar(PB);
UnmapViewOfFile(PMap);
end;
CloseHandle(MapH);
end;
CloseHandle(FileH);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
GetLastLines(5,"e:\uploads.txt",Memo1.Lines);
end;


Игорь Шевченко   (2003-02-07 15:31:00) [9]

MMF в данном случае лучше...


Sherbacov   (2003-02-07 15:15:00) [10]

Спасибо, все работает.


MBo   (2003-02-07 01:11:00) [11]

>и если вдруг не 9 строку надо...
С этим, думаю, понятно

>больше чем 4096
Надо закладывать некие разумные предположения, можно устанавливать размер буфера в зависимости от количества нужных строк, а если в нем оказалось мало строк, прочитать еще кусок


Palladin   (2003-02-07 01:02:00) [12]

сорри...
не доконца разобрал, что именно делает процедура, но вот если произойдет ситуация если сумма 9 последних строк будет больше чем 4096 и если вдруг не 9 строку надо...

ненадежно, однако :)


MBo   (2003-02-07 00:51:00) [13]

>Palladin
>а чем собственно говоря это отличается от
Ну сам подумай.


Palladin   (2003-02-06 23:52:00) [14]

2 MBo
а чем собственно говоря это отличается от

procedure TStrings.LoadFromStream(Stream: TStream);
var
Size: Integer;
S: string;
begin
BeginUpdate;
try
Size := Stream.Size - Stream.Position;
SetString(S, nil, Size);
Stream.Read(Pointer(S)^, Size);
SetTextStr(S);
finally
EndUpdate;
end;
end;



procedure TStrings.SetTextStr(const Value: string);
var
P, Start: PChar;
S: string;
begin
BeginUpdate;
try
Clear;
P := Pointer(Value);
if P <> nil then
while P^ <> #0 do
begin
Start := P;
while not (P^ in [#0, #10, #13]) do Inc(P);
SetString(S, Start, P - Start);
Add(S);
if P^ = #13 then Inc(P);
if P^ = #10 then Inc(P);
end;
finally
EndUpdate;
end;
end;


Sherbacov   (2003-02-06 23:46:00) [15]

Спасибо, вот это я и искал.


Palladin   (2003-02-06 23:44:00) [16]

хоть бы текст сообщения об ошибке сюда кинул.
может у тебя там EOutOfMemory :))


MBo   (2003-02-06 23:43:00) [17]


procedure TForm1.Button1Click(Sender: TObject);
var fs:TFileStream;
buf:array[0..4095] of char;
NStr,i,j,BufSize,OldPos:integer;
s:string;
begin
NStr:=9;
fs:=TFileStream.Create("e:\unit1.pas",fmOpenRead or fmShareDenyNone);
BufSize:=4096;
if fs.Size<BufSize then
BufSize:=fs.Size;
fs.Seek(-BufSize,soFromEnd);
fs.Read(buf,bufsize);
if buf[bufsize-1]=#10 then
OldPos:=BufSize-1
else
OldPos:=BufSize+1;
j:=0;
for i:=bufsize-2 downto 0 do begin
if buf[i]=#10 then begin
SetLength(s,OldPos-i-2);
Move(buf[i+1],s[1],OldPos-i-2);
OldPos:=i;
Memo1.Lines.Add(s);
inc(j);
if j=NStr then Break;
end;
end;
fs.Free;
end;



Sherbacov   (2003-02-06 23:42:00) [18]

Но, файлы начиная с 200 мегов, вообще не работает


Palladin   (2003-02-06 23:39:00) [19]

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


Наверх

Титульная страница Поиск, карта сайта Написать письмо