Я хочу открыть двоичный файл 50 МБ и читать только последние 4 байта и преобразовывать его в строку для какой-либо цели.Чтение байтов из файла в нужном месте с помощью Inno Setup
Единственный способ, которым я нашел это сделать, это использовать LoadStringFromFile
, чтобы загрузить файл целиком в память, а затем скопировать последние 4 байта, однако этот метод очень медленный, потому что бинарный файл тяжелый.
Есть ли лучший способ сделать это в скрипте Inno Setup?
Update:
Это окончательная рабочая функция, я редактировал от ответа Мартина Přikryl в
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;
Update 2:
Кроме того, эторугой большой рабочий функция, которая написана TLama и должен пометить как ответ тоже:
[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;
Лучше использовать 'Seek' с происхождением' soEnd'. Вы будете сохранять накладные расходы на поиск начала и конца при определении размера потока. – TLama
@TLama Конечно, спасибо, я упустил «Seek». Хотя я не смог использовать 'TFileStream'. И «Чтение», и «ReadBuffer» имеют неправильную подпись. «Буфер» не является аргументом «по рефлектору». –
Все должно быть хорошо. Вы могли бы забыть выделить буфер. Это то, что 'ReadBuffer' не делает для вас. Хуже того, что в Unicode Inno Setup вам придется разбивать каждый символ на байты, чтобы получить символы ANSI из Unicode. Должен быть достаточно массив байтовых параметров. Постскриптум OP знает о функции LoadStringFromFile. – TLama