Здравствуйте, есть ли возможность очень быстро писать и читать строки с файла сейчас использую Buffered FileStream (доступ к буфферизованным файлам) и пишу обычно Append и это очень медленно на мой взгляд (
Код:
//Читаю n строку с файла так:
uses
BufferedFileStream;
function GrabNew(const AFileName: string; ALine: Integer): string;
var
fs: TReadOnlyCachedFileStream;
buf: packed array[0..4096] of Char;
bufRead: Integer;
bufPos: PChar;
lineStart: PChar;
tmp: string;
begin
fs := TReadOnlyCachedFileStream.Create(AFileName);
try
Dec(ALine);
bufRead := 0;
bufPos := nil;
{ read the first line specially }
if ALine = 0 then
begin
bufRead := fs.Read(buf, SizeOf(buf));
if bufRead = 0 then
raise Exception.Create('Line not found');
//work:=false;
bufPos := buf;
end else
while ALine > 0 do
begin
{ read in a buffer }
bufRead := fs.Read(buf, SizeOf(buf));
if bufRead = 0 then
raise Exception.Create('Line not found');
//work:=false;
bufPos := buf;
while (bufRead > 0) and (ALine > 0) do
begin
if bufPos^ = #10 then
Dec(ALine);
Inc(bufPos);
Dec(bufRead);
end;
end;
{ Found the beginning of the line at bufPos... scan for end.
2 cases:
1) we"ll find it before the end of this buffer
2) it"ll go beyond this buffer and into n more buffers }
lineStart := bufPos;
while (bufRead > 0) and (bufPos^ <> #10) do
begin
Inc(bufPos);
Dec(bufRead);
end;
{ if bufRead is positive, we"ll have found the end and we can leave. }
SetString(Result, lineStart, bufPos - lineStart);
{ determine if there are more buffers to process }
while bufRead = 0 do
begin
bufRead := fs.Read(buf, SizeOf(buf));
lineStart := buf;
bufPos := buf;
while (bufRead > 0) and (bufPos^ <> #10) do
begin
Inc(bufPos);
Dec(bufRead);
end;
SetString(tmp, lineStart, bufPos - lineStart);
Result := Result + tmp;
end;
finally
Freeandnil(fs);
end;
delete(Result,length(Result),1);
end;
//Записываю в файл строку так:
if not FileExists (Extractfilepath(paramstr(0))+'log.txt') then begin
Assignfile(Zapros, Extractfilepath(paramstr(0))+'log.txt');
Rewrite(logfile);
Closefile(logfile);
end;
Append(logfile);
Writeln(logfile,logstring);
Closefile(logfile);
Это очень медленно наткнулся на процедуру ассинхронного чтения и записи но оно не работает (
Код:
function AsyncReadFile(const FileName: string;const Overlapped:TOverlapped): cardinal;
const
BufSize = 1024*1024;
var
Fi: THandle;
pBuf:array [0..1] of pointer;//нужно два буфера, в первый читаем, а второй передаем для обработки
BigSize:array [0..1] of Cardinal;
Count:array[0..1] of Cardinal;
index:Cardinal; // определяет в какой буфер читать, а какой передавать на обработку
Size:^Int64; // размер файла
begin
Result:=$FFFFFFFF;
Fi:=CreateFile(Pchar(FileName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED or FILE_FLAG_SEQUENTIAL_SCAN,0); //режим доступа асинхронный + просим систему кешировать файл
if Fi = INVALID_HANDLE_VALUE then exit;
GetMem(pBuf[0],BufSize);
GetMem(pBuf[1],BufSize);
if (pBuf[0] = nil)or(pBuf[1] = nil) then exit;
BigSize[0]:=GetFileSize(fi,@BigSize[1]); //получаем размер файла
Size:=@BigSize[0];
if Size^ <> 0 then
begin
index:=0;
//первоче чтение
count[index and 1]:=BufSize;
if Size^ < BufSize then count[index and 1]:=Size^;
ResetEvent(Overlapped.hEvent);
ReadFile(Fi,pBuf[index and 1]^,count[index and 1],count[index and 1],@Overlapped);
GetOverlappedResult(Fi,Overlapped,count[index and 1],true);
while count[index and 1]<>0 do
begin
Size^:=Size^ - count[index and 1];
inc(index);
//следующий запрос на чтение
ResetEvent(Overlapped.hEvent);
count[index and 1]:=BufSize;
if Size^ < BufSize then count[index and 1]:=Size^;
ReadFile(Fi,pBuf[index and 1]^,count[index and 1],count[index and 1],@Overlapped);
dec(index);
{
здесь любые ваши вычисления.
pBuf[ (index and 1)] - указатель на прочитанные данные.
Count[ (index and 1)] - размер прочитанных данных.
}
//ожидаем завершения чтения
inc(index);
GetOverlappedResult(Fi,Overlapped,count[index and 1],true);
end;
end;
Result:=not Result;
FreeMem(pBuf[0]);
FreeMem(pBuf[1]);
CloseHandle(Fi);
end;
procedure Tform1.Button1Click(Sender: TObject);
var
OverRead:TOverlapped;
res:cardinal;
begin
ZeroMemory(@OverRead,sizeof(OverRead));
OverRead.hEvent := CreateEvent(nil,true,false,nil);
if opendialog1.execute then
res:= AsyncReadFile(opendialog1.filename,OverRead);
memo1.lines.add(res??????); //не понимаю как вывести или делать cardinaltostring
CloseHandle(OverRead.hEvent);
end;
end;