![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Открытие большого файла [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 секунды перелопатилось...
ничесе запросы...