你不能直接绕过这个错误,因为 astring
和 anarray[] of Byte
不能直接赋值。
由于二进制内容(#0
特别是字符,或0x00
十六进制值 (C/C++))无论如何都无法显示TMemo
(文本将在第一个#0
值处终止),因此您需要将其替换为某些内容。
克服编译器错误的最简单方法是将数组从 更改为,array[] of Byte
它array[] of AnsiChar
可以直接分配给 a 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
,因为第四个字节是 a#0
并且备忘录终止了字符串。
要克服此限制,您需要将所有#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;
注意:如果您实际上是在读取整个二进制文件而不仅仅是第一个缓冲区,则最后一个缓冲区可能不会完全充满文件内容(您可能在最后一次读取时没有读取完整的缓冲区)。在这种情况下,您想用 a 标记缓冲区的结尾,#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;
这是读取单个缓冲区已满的输出: