Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

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