Противоламерская Оборона, имею медаль"За защиту UNIX'а от Мелкомягких"
Данный модуль позволяет читать и записывать файлы формата Unix.
unit StreamFile;
interfaceuses
SysUtils;
procedure AssignStreamFile(var F: Text; Filename: string);
implementationconst
BufferSize = 128;
type
TStreamBuffer = array[1..High(Integer)] of Char;
TStreamBufferPointer = ^TStreamBuffer;
TStreamFileRecord = recordcase 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;
beginwith TStreamFileRecord(F.UserData) dobegin
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;
procedureRead(var Data: TStreamFileRecord);
procedure CopyData;
beginwhile (F.BufEnd < Sizeof(F.Buffer) - 2)
and (Data.BufferOffset <= Data.ReadCount)
and (Data.Buffer[Data.BufferOffset] <> #10) dobegin
F.Buffer[F.BufEnd] := Data.Buffer^[Data.BufferOffset];
Inc(Data.BufferOffset);
Inc(F.BufEnd);
end;
if Data.Buffer[Data.BufferOffset] = #10 thenbegin
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 := '';
repeatbeginif (Data.ReadCount = 0) or (Data.BufferOffset > Data.ReadCount) thenbegin
Data.BufferOffset := 1;
Data.ReadCount := FileRead(Data.FileHandle, Data.Buffer^, BufferSize);
end;
CopyData;
enduntil (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;
beginwith TStreamFileRecord(F.UserData) dobegin
Destination := 0;
for II := 0 to F.BufPos - 1 dobeginif F.Buffer[II] <> #13 thenbegin
Inc(Destination);
Buffer^[Destination] := F.Buffer[II];
end;
end;
Status := FileWrite(FileHandle, Buffer^, Destination);
F.BufPos := 0;
Result := 0;
end;
end;
begincase 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;
beginwith TStreamFileRecord(F.UserData) dobegin
FreeMem(Buffer);
FileClose(FileHandle);
end;
Result := 0;
end;
procedure AssignStreamFile(var F: Text; Filename: string);
beginwith TTextRec(F) dobegin
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, которая обеспечивает чтение и запись файлов в формате Unix. Единица включает в себя несколько процедур и функций, которые позволяют открыть, закрыть, прочитать из файла и записать в файл в формате Unix.
Единица StreamFile имеет четыре основные процедуры:
StreamFileOpen: Открывает файл в формате Unix для чтения или записи.
StreamFileInOut: Читает данные из файла и записывает их в буфер, или пишет данные из буфера в файл.
StreamFileFlush: Очищает буферized вывод в файл.
StreamFileClose: Закрывает файл.
Единица также включает в себя процедуру AssignStreamFile, которая присваивает имя файла текстовому рекорду и настраивает файл для чтения или записи.
Вот некоторые предложения по улучшению:
Обработка ошибок: Текущая реализация не обрабатывает ошибки хорошо. Например, если файл не может быть открыт, функция StreamFileOpen возвращает -1, но не предоставляет никакой информации о ошибке.
Организация кода: Код немного сложен из-за своей сложности и отсутствия четкой организации. Лучше разбить его на более маленькие процедуры или функции, каждая из которых обрабатывает конкретную задачу.
Выполнение: Процедура StreamFileInOut использует буфер для чтения из файла и записи в файл, что может улучшить производительность. Однако размер буфера жестко закодирован в 128 символов, что может не быть оптимальным для всех файлов. Лучше сделать размер буфера настраиваемым или динамическим.
Стиль кода: Код использует смесь синтаксиса Pascal и C, что может сделать его более сложным для чтения и поддержки. Лучше использовать единый стиль кодирования throughout единицы.
Вот альтернативное решение, которое решает эти проблемы:
unitStreamFile;interfaceusesSysUtils;typeTStreamFile=classprivateFHandle:Integer;FBuffer:string;FBufferSize:Integer;publicconstructorCreate(constFileName:string);destructorDestroy;override;procedureRead(varData:string);procedureWrite(constData:string);functionFlush:Integer;functionClose:Integer;end;implementationconstructorTStreamFile.Create(constFileName:string);beginFHandle:=FileOpen(FileName,fmShareDenyNoneorfmOpenRead);ifFHandle=-1thenraiseException.Create('Failed to open file');FBufferSize:=128;// настраиваемый размер буфераFBuffer:='';end;destructorTStreamFile.Destroy;beginClose;inherited;end;procedureTStreamFile.Read(varData:string);varStatus:Integer;BufferSize:Integer;II:Integer;beginifFHandle=-1thenraiseException.Create('File is closed');SetLength(FBuffer,FBufferSize);Status:=FileRead(FHandle,PChar(FBuffer),FBufferSize);Data:=FBuffer;whileStatus>0dobeginBufferSize:=Length(FBuffer);forII:=1toBufferSizedoifFBuffer[II]=#10thenBreak;SetLength(FBuffer,II-1);Status:=FileRead(FHandle,PChar(FBuffer),FBufferSize);end;end;procedureTStreamFile.Write(constData:string);varStatus:Integer;beginifFHandle=-1thenraiseException.Create('File is closed');Status:=FileWrite(FHandle,PChar(Data)+1,Length(Data));end;functionTStreamFile.Flush:Integer;beginResult:=0;end;functionTStreamFile.Close:Integer;beginifFHandle=-1thenraiseException.Create('File is already closed');FileClose(FHandle);FHandle:=-1;Result:=0;end;procedureAssignStreamFile(varF:Text;FileName:string);beginwithTTextRec(F)dobeginMode:=fmClosed;BufPtr:=@Buffer;BufSize:=Sizeof(Buffer);OpenFunc:=@TStreamFile.Create;InOutFunc:=@TStreamFile.ReadWrite;FlushFunc:=@TStreamFile.Flush;CloseFunc:=@TStreamFile.Close;StrPLCopy(Name,FileName,Sizeof(Name)-1);end;end;end.
В этом решении используется класс TStreamFile для управления файловыми операциями. Класс имеет методы для чтения и записи данных, очищения буфера, закрытия файла и создания нового экземпляра класса. Процедура AssignStreamFile присваивает имя файла текстовому рекорду и настраивает файл для чтения или записи.
Модуль StreamFile для работы с Unix-файлами: чтение и запись файлов в текстовом формате.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.