Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Unix-строки (чтение и запись Unix-файлов)

Delphi , Синтаксис , Текст и Строки

Unix-строки (чтение и запись Unix-файлов)

Противоламерская Оборона, имею медаль"За защиту UNIX'а от Мелкомягких"

Данный модуль позволяет читать и записывать файлы формата Unix.


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, которая обеспечивает чтение и запись файлов в формате Unix. Единица включает в себя несколько процедур и функций, которые позволяют открыть, закрыть, прочитать из файла и записать в файл в формате Unix.

Единица StreamFile имеет четыре основные процедуры:

  1. StreamFileOpen: Открывает файл в формате Unix для чтения или записи.
  2. StreamFileInOut: Читает данные из файла и записывает их в буфер, или пишет данные из буфера в файл.
  3. StreamFileFlush: Очищает буферized вывод в файл.
  4. StreamFileClose: Закрывает файл.

Единица также включает в себя процедуру AssignStreamFile, которая присваивает имя файла текстовому рекорду и настраивает файл для чтения или записи.

Вот некоторые предложения по улучшению:

  1. Обработка ошибок: Текущая реализация не обрабатывает ошибки хорошо. Например, если файл не может быть открыт, функция StreamFileOpen возвращает -1, но не предоставляет никакой информации о ошибке.
  2. Организация кода: Код немного сложен из-за своей сложности и отсутствия четкой организации. Лучше разбить его на более маленькие процедуры или функции, каждая из которых обрабатывает конкретную задачу.
  3. Выполнение: Процедура StreamFileInOut использует буфер для чтения из файла и записи в файл, что может улучшить производительность. Однако размер буфера жестко закодирован в 128 символов, что может не быть оптимальным для всех файлов. Лучше сделать размер буфера настраиваемым или динамическим.
  4. Стиль кода: Код использует смесь синтаксиса Pascal и C, что может сделать его более сложным для чтения и поддержки. Лучше использовать единый стиль кодирования throughout единицы.

Вот альтернативное решение, которое решает эти проблемы:

unit StreamFile;

interface

uses
  SysUtils;

type
  TStreamFile = class
  private
    FHandle: Integer;
    FBuffer: string;
    FBufferSize: Integer;
  public
    constructor Create(const FileName: string);
    destructor Destroy; override;

    procedure Read(var Data: string);
    procedure Write(const Data: string);

    function Flush: Integer;
    function Close: Integer;
  end;

implementation

constructor TStreamFile.Create(const FileName: string);
begin
  FHandle := FileOpen(FileName, fmShareDenyNone or fmOpenRead);
  if FHandle = -1 then
    raise Exception.Create('Failed to open file');

  FBufferSize := 128; // настраиваемый размер буфера
  FBuffer := '';
end;

destructor TStreamFile.Destroy;
begin
  Close;
  inherited;
end;

procedure TStreamFile.Read(var Data: string);
var
  Status: Integer;
  BufferSize: Integer;
  II: Integer;
begin
  if FHandle = -1 then
    raise Exception.Create('File is closed');

  SetLength(FBuffer, FBufferSize);
  Status := FileRead(FHandle, PChar(FBuffer), FBufferSize);
  Data := FBuffer;

  while Status > 0 do
  begin
    BufferSize := Length(FBuffer);
    for II := 1 to BufferSize do
      if FBuffer[II] = #10 then
        Break;
    SetLength(FBuffer, II - 1);

    Status := FileRead(FHandle, PChar(FBuffer), FBufferSize);
  end;
end;

procedure TStreamFile.Write(const Data: string);
var
  Status: Integer;
begin
  if FHandle = -1 then
    raise Exception.Create('File is closed');

  Status := FileWrite(FHandle, PChar(Data) + 1, Length(Data));
end;

function TStreamFile.Flush: Integer;
begin
  Result := 0;
end;

function TStreamFile.Close: Integer;
begin
  if FHandle = -1 then
    raise Exception.Create('File is already closed');

  FileClose(FHandle);
  FHandle := -1;
  Result := 0;
end;

procedure AssignStreamFile(var F: Text; FileName: string);
begin
  with TTextRec(F) do
  begin
    Mode := 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




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Текст и Строки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 13:18:43/0.006572961807251/1