Read bytes from file at desired position with Inno Setup

六眼飞鱼酱① 提交于 2019-11-28 00:32:38

You can use TFileStream support class:

TStream = class(TObject)
  function Read(Buffer: String; Count: Longint): Longint;
  function Write(Buffer: String; Count: Longint): Longint;
  function Seek(Offset: Longint; Origin: Word): Longint;
  procedure ReadBuffer(Buffer: String; Count: Longint);
  procedure WriteBuffer(Buffer: String; Count: Longint);
  function CopyFrom(Source: TStream; Count: Longint): Longint;
  property Position: Longint; read write;
  property Size: Longint; read write;
end;

THandleStream = class(TStream)
  constructor Create(AHandle: Integer);
  property Handle: Integer; read;
end;

TFileStream = class(THandleStream)
  constructor Create(Filename: String; Mode: Word);
end;

Use the .Seek(-4, soFromEnd) property to seek the read pointer to the desired position.

A complication is that the TStream works with characters not bytes, so you have to convert Unicode strings that your read back to bytes.

When reading just four bytes, it's way easier to read byte by byte, preventing any multibyte conversions:

procedure ReadFileEnd;
var
  Stream: TFileStream;
  Buffer: string;
  Count: Integer;
  Index: Integer;
begin
  Count := 4;

  Stream := TFileStream.Create('my_binary_file.dat', fmOpenRead);

  try
    Stream.Seek(-Count, soFromEnd);

    SetLength(Buffer, 1);
    for Index := 1 to Count do
    begin
      Stream.ReadBuffer(Buffer, 1);
      Log(Format('Byte %2.2x: %2.2x', [Index, Ord(Buffer[1])]));
    end;
  finally
    Stream.Free;
  end;
end;

Here's a generic alternative from by @TLama that efficiently works for arbitrary large read:
https://pastebin.com/nzGEdXVj


By the way, for me LoadStringFromFile function seems to be efficient enough to load 50 MB file. It takes only 40 ms.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!