gpt4 book ai didi

delphi - 在Delphi中读取二进制文件

转载 作者:行者123 更新时间:2023-12-03 18:01:05 24 4
gpt4 key购买 nike

我想读取一个二进制文件并在备忘录中显示结果,但不知道如何处理这个错误:“不兼容的类型:‘string’和‘Array’”,代码是这样的

unit yo;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
F: TFileStream;
Buffer: array [0 .. 1023] of byte;
begin

F := TFileStream.Create(ExtractFilePath(Application.ExeName)
+ 'yo.exe', fmOpenRead);

while F.Position < F.Size do
begin

F.Read(Buffer, 1024);
Memo1.Lines.Add(Buffer);

end;

F.Free;

end;

设法避免此错误并无错误地运行程序?

谁能帮帮我?

最佳答案

你不能直接绕过这个错误,因为 stringarray[] of Byte 不能直接赋值。

因为二进制内容(特别是 #0 字符,或 0x00 十六进制值 (C/C++))不会在 TMemo 中显示 无论如何(文本将在第一个 #0 值处终止),您需要用某些东西替换它。

克服编译器错误的最简单方法是将数组从 array[] of Byte 更改为 array[] of AnsiChar , 可以直接分配给 string (或类型转换为一个):

var
Buffer: array[0..1023] of AnsiChar;
TempStr: string;
begin
// Fill buffer from stream
TempStr := Buffer;
Memo1.Lines.Add(TempStr);
// The next line eliminates the need for `TempStr`
// Memo1.Lines.Add(String(Buffer));
end;

但是,就像我说的,这不会解决在备忘录中显示的问题。例如,当实际读取 Windows 可执行文件时,第一个缓冲区显示 MZP,因为第四个字节是 #0 并且 memo 终止了字符串。

要克服此限制,您需要将所有 #0 字符替换为其他字符。当然,这样做的问题是您替换它的任何值实际上也可能出现在可执行文件中(因为它们是字节,所以只有 256 个可能的值)。同样,简单的解决方案是将所有 #0 字符替换为 0 (#216):

var
Buffer: array[0..1023] of AnsiChar;
i: Integer;
TempStr: string;
begin
// Fill buffer as before
for i := Low(Buffer) to High(Buffer) do
if Buffer[i] = #0 then
Buffer[i] := `Ø`; // Try #144 instead
TempStr := Buffer;
Memo1.Lines.Add(TempStr);
// You can still eliminate the string variable by typecasting
// Memo1.Lines.Add(String(TempStr));
end;

下面是 TForm.FormCreate 事件的代码,它实际上从 Delphi 控制台应用程序读取 1K 缓冲区,进行上述替换,并在 TMemo 中显示内容。将 TMemo 拖放到窗体上,将其 Alignment 属性设置为 alClient,并将 ScrollBars 设置为 ssVertical。向表单添加一个 FormCreate 事件处理程序,并为该事件使用以下代码:

procedure TForm1.FormCreate(Sender: TObject);
var
Stream: TFileStream;
Buffer: array[0..1023] of AnsiChar;
TempStr: string;
i: Integer;
begin
Memo1.Clear;
// Populate buffer elements
Stream := TFileStream.Create('D:\Temp\Project2.exe', fmOpenRead);
try
Stream.Read(Buffer[0], SizeOf(Buffer));
finally
Stream.Free;
end;
// Replace null (#0) values with #216 (Ø)
for i := Low(Buffer) to High(Buffer) do
if Buffer[i] = #0 then
Buffer[i] := 'Ø';
TempStr := Buffer;
Memo1.Lines.Add(TempStr);
end;

注意:如果您实际上正在读取整个二进制文件而不是第一个缓冲区,则最后一个缓冲区可能不会完全充满文件内容(您可能在最后一次读取时没有读取完整的缓冲区)。在这种情况下,您希望使用 #0 标记缓冲区的末尾,以便备忘录正确显示该部分缓冲区。您可以更改 for 循环以使用如下内容:

for i := Low(Buffer) to High(Buffer) do
begin
if (i = BytesRead) then
begin
Buffer[i] := #0; // Mark the end of the buffer and exit loop;
Break;
end
else if (Buffer[i] = #0) then
Buffer[i] := 'Ø';
end;

这是读取单个缓冲区已满的输出:

Executable displayed in TMemo

关于delphi - 在Delphi中读取二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17602044/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com