我正在使用Delphi 2009。
我想在备忘录中查看文件的内容(十六进制)。
我正在使用此代码:
var
Buffer:String;
begin
Buffer := '';
AssignFile(sF,Source); //Assign file
Reset(sF);
repeat
Readln(sF,Buffer); //Load every line to a string.
TempChar:=StrToHex(Buffer); //Convert to Hex using the function
...
until EOF(sF);
end;
function StrToHex(AStr: string): string;
var
I ,Len: Integer;
s: chr (0)..255;
//s:byte;
//s: char;
begin
len:=length(AStr);
Result:='';
for i:=1 to len do
begin
s:=AStr[i];
//The problem is here. Ord(s) is giving false values (251 instead of 255)
//And in general the output differs from a professional hex editor.
Result:=Result +' '+IntToHex(Ord(s),2)+'('+IntToStr(Ord(s))+')';
end;
Delete(Result,1,1);
end;
当我将变量“ s ”声明为 char 时(我知道char最多为255)我得到的结果十六进制值高达65535!
当我将变量“ s ”声明为字节或 chr(0).. 255 时,它会输出不同的十六进制值,任何十六进制编辑器!
为什么?我怎样才能看到正确的值?
检查图像是否存在差异。
第一张图片:专业十六进制编辑器。
第二张图片:功能输出到备忘录。
谢谢。
答案 0 :(得分:10)
您的Delphi 2009启用了unicode,因此Char
实际为WideChar
,这是一个2字节,16位无符号值,可以包含0到65535之间的值。
您可以将所有Char
声明更改为AnsiChar
,将所有String
声明更改为AnsiString
,但这不是可行方式。您应该删除Pascal I / O以支持现代基于流的I / O,使用TFileStream
,并且不要将二进制数据视为Char
。
控制台演示:
program Project26;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;
var F: TFileStream;
Buff: array[0..15] of Byte;
CountRead: Integer;
HexText: array[0..31] of Char;
begin
F := TFileStream.Create('C:\Temp\test', fmOpenRead or fmShareDenyWrite);
try
CountRead := F.Read(Buff, SizeOf(Buff));
while CountRead <> 0 do
begin
BinToHex(Buff, HexText, CountRead);
WriteLn(HexText); // You could add this to the Memo
CountRead := F.Read(Buff, SizeOf(Buff));
end;
finally F.Free;
end;
end.
答案 1 :(得分:9)
在Delphi 2009中,Char
与WideChar
相同,即 Unicode字符。宽字符占用两个字节。您想使用AnsiChar
。在Delphi 2009之前(即在Unicode Delphi之前),Char
与AnsiChar
是一样的。
此外,您不应使用ReadLn
。您将文件视为具有文本文件行结尾的文本文件!这是一般文件!它可能根本没有任何文本文件行结尾!
答案 2 :(得分:7)
为了更容易阅读输出,并且看起来更好,您可能希望使用这个简单的十六进制转储格式化程序。
HexDump过程将一个内存区域转换为两个8字节的十六进制行的TStrings,以及16个ascii字符
例如
406563686F206F66 660D0A6966206578 @echo off..if ex
69737420257E7331 5C6E756C20280D0A ist %~s1\nul (..
0D0A290D0A ..)..
以下是转储格式函数的代码
function HexB (b: Byte): String;
const HexChar: Array[0..15] of Char = '0123456789ABCDEF';
begin
result:= HexChar[b shr 4]+HexChar[b and $0f];
end;
procedure HexDump(var data; size: Integer; s: TStrings);
const
sepHex=' ';
sepAsc=' ';
nonAsc='.';
var
i : Integer;
hexDat, ascDat : String;
buff : Array[0..1] of Byte Absolute data;
begin
hexDat:='';
ascDat:='';
for i:=0 to size-1 do
begin
hexDat:=hexDat+HexB(buff[i]);
if ((buff[i]>31) and (buff[i]<>255)) then
ascDat:=ascDat+Char(buff[i])
else
ascDat:=ascDat+nonAsc;
if (((i+1) mod 16)<>0) and (((i+1) mod 8)=0) then
hexDat:=hexDat+sepHex;
if ((i+1) mod 16)=0 then
begin
s.Add(hexdat+sepAsc+ascdat);
hexdat:='';
ascdat:='';
end;
end;
if (size mod 16)<>0 then
begin
if (size mod 16)<8 then
hexDat:=hexDat+StringOfChar(' ',(8-(size mod 8))*2)
+sepHex+StringOfChar(' ',16)
else
hexDat:=hexDat+StringOfChar(' ',(16-(size mod 16))*2);
s.Add(hexDat + sepAsc + ascDat);
end;
end;
这是一个完整的代码示例,用于将文件内容转储到备注字段中。
procedure TForm1.Button1Click(Sender: TObject);
var
FStream: TFileStream;
buff: array[0..$fff] of Byte;
nRead: Integer;
begin
FStream := TFileStream.Create(edit1.text, fmOpenRead or fmShareDenyWrite);
try
repeat
nRead := FStream.Read(Buff, SizeOf(Buff));
if nRead<>0 then
hexdump(buff,nRead,memo1.lines);
until nRead=0;
finally
F.Free;
end;
end;
答案 3 :(得分:3)
string
为UnicodeString
。如果要使用单字节字符串,请使用AnsiString
或RawByteString
。
请参阅String types。