Unix-строки (чтение и запись Unix-файлов)
01.01.2007
unit StreamFile; interface uses SysUtils; procedure AssignStreamFile(var F: Text; Filename: string); implementation const BufferSize = 128; type TStreamBuffer = array[1..High(Integer)] of Char; TStreamBufferPointer = ^TStreamBuffer; TStreamFileRecord = record case Integer of 1: ( Filehandle: Integer; Buffer: TStreamBufferPointer; BufferOffset: Integer; ReadCount: Integer; ); 2: ( Dummy: array[1..32] of Char ) end; function StreamFileOpen(var F: TTextRec): Integer; var Status: Integer; begin with TStreamFileRecord(F.UserData) do begin GetMem(Buffer, BufferSize); case F.Mode of fmInput: FileHandle := FileOpen(StrPas(F.Name), fmShareDenyNone); fmOutput: FileHandle := FileCreate(StrPas(F.Name)); fmInOut: begin FileHandle := FileOpen(StrPas(F.Name), fmShareDenyNone or fmOpenWrite or fmOpenRead); if FileHandle <> -1 then status := FileSeek(FileHandle, 0, 2); { Перемещаемся в конец файла. } F.Mode := fmOutput; end; end; BufferOffset := 0; ReadCount := 0; F.BufEnd := 0; { В этом месте подразумеваем что мы достигли конца файла (eof). } if FileHandle = -1 then Result := -1 else Result := 0; end; end; function StreamFileInOut(var F: TTextRec): Integer; procedure Read(var Data: TStreamFileRecord); procedure CopyData; begin while (F.BufEnd < Sizeof(F.Buffer) - 2) and (Data.BufferOffset <= Data.ReadCount) and (Data.Buffer[Data.BufferOffset] <> #10) do begin F.Buffer[F.BufEnd] := Data.Buffer^[Data.BufferOffset]; Inc(Data.BufferOffset); Inc(F.BufEnd); end; if Data.Buffer[Data.BufferOffset] = #10 then begin F.Buffer[F.BufEnd] := #13; Inc(F.BufEnd); F.Buffer[F.BufEnd] := #10; Inc(F.BufEnd); Inc(Data.BufferOffset); end; end; begin F.BufEnd := 0; F.BufPos := 0; F.Buffer := ''; repeat begin if (Data.ReadCount = 0) or (Data.BufferOffset > Data.ReadCount) then begin Data.BufferOffset := 1; Data.ReadCount := FileRead(Data.FileHandle, Data.Buffer^, BufferSize); end; CopyData; end until (Data.ReadCount = 0) or (F.BufEnd >= Sizeof(F.Buffer) - 2); Result := 0; end; procedure Write(var Data: TStreamFileRecord); var Status: Integer; Destination: Integer; II: Integer; begin with TStreamFileRecord(F.UserData) do begin Destination := 0; for II := 0 to F.BufPos - 1 do begin if F.Buffer[II] <> #13 then begin Inc(Destination); Buffer^[Destination] := F.Buffer[II]; end; end; Status := FileWrite(FileHandle, Buffer^, Destination); F.BufPos := 0; Result := 0; end; end; begin case F.Mode of fmInput: Read(TStreamFileRecord(F.UserData)); fmOutput: Write(TStreamFileRecord(F.UserData)); end; end; function StreamFileFlush(var F: TTextRec): Integer; begin Result := 0; end; function StreamFileClose(var F: TTextRec): Integer; begin with TStreamFileRecord(F.UserData) do begin FreeMem(Buffer); FileClose(FileHandle); end; Result := 0; end; procedure AssignStreamFile(var F: Text; Filename: string); begin with TTextRec(F) do begin Mode := fmClosed; BufPtr := @Buffer; BufSize := Sizeof(Buffer); OpenFunc := @StreamFileOpen; InOutFunc := @StreamFileInOut; FlushFunc := @StreamFileFlush; CloseFunc := @StreamFileClose; StrPLCopy(Name, FileName, Sizeof(Name) - 1); end; end; end.
Взято из Советов по Delphi от Валентина Озерова
Сборник Kuliba