title: Read bytes from file at desired position with Inno Setup
body: <p>I want to open a 50 MB binary file and read only the last 4 bytes and convert it to string for some purpose.</p>
  
  <p>The only way I found to do it now is using <code>LoadStringFromFile</code>, to load the file entirely on the memory then copy that last 4 bytes, however this method is very slow because the binary file is heavy.</p>
  
  <p>Is there any better way to do it in Inno Setup script?</p>
  
  <p><strong>Update :</strong></p>
  
  <hr>
  
  <p>This is a final working function that I edited from Martin Prikryl's answer</p>
  
  <pre class="lang-pascal prettyprint-override"><code>function readlast4byte() : AnsiString;
  var
    Stream: TFileStream;
    Buffer: string;
    Count: Integer;
    Index: Integer;
  begin
    Count := 4;
  
    Stream := TFileStream.Create('C:\test.txt', fmOpenRead);
  
    try
      Stream.Seek(-Count, soFromEnd);
  
      SetLength(Buffer, 1);
      SetLength(Result, Count);
      for Index := 1 to Count do
      begin
        Stream.ReadBuffer(Buffer, 1);
        Result[Index] := Chr(Ord(Buffer[1]))  ;
      end;
    finally
      Stream.Free;
    end;
  end;
  </code></pre>
  
  <hr>
  
  <p><strong>Update 2 :</strong></p>
  
  <p>Also this is another great working function that written by TLama and should mark as answer too:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>[Code]
  #IFNDEF Unicode
    #DEFINE CharSize 1
  #ELSE
    #DEFINE CharSize 2
  #ENDIF
  
  type
    TSeekOrigin = (
      soBeginning,
      soCurrent,
      soEnd
    );
  
  #IFDEF UNICODE
  function BufferToAnsi(const Buffer: string): AnsiString;
  var
    W: Word;
    I: Integer;
  begin
    SetLength(Result, Length(Buffer) * 2);
    for I := 1 to Length(Buffer) do
    begin
      W := Ord(Buffer[I]);
      Result[(I * 2)] := Chr(W shr 8); // high byte
      Result[(I * 2) - 1] := Chr(Byte(W)); // low byte
    end;
  end;
  #ENDIF
  
  function ReadStringFromFile(const FileName: string; Origin: TSeekOrigin; Offset, Length: Integer;
    var S: AnsiString): Boolean;
  var
    Buffer: string;
    Stream: TFileStream;
  begin
    Result := True;
    try
      Stream := TFileStream.Create(FileName, fmOpenRead);
      try
        Stream.Seek(Offset, Ord(Origin));
        SetLength(Buffer, Length div {#CharSize});
        Stream.ReadBuffer(Buffer, Length);
        #IFNDEF UNICODE
          S := Buffer;
        #ELSE
          S := BufferToAnsi(Buffer);
        #ENDIF
      finally
        Stream.Free;
      end;
    except
      Result := False;
    end;
  
      end;
  </code></pre>