文件的十六进制视图

发布于 2024-11-15 05:25:24 字数 1310 浏览 2 评论 0原文

我正在使用 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”声明为bytechr (0)..255时,与任何十六进制编辑器相比,它输出不同的十六进制值!

这是为什么?我怎样才能看到正确的值?

检查图像是否存在差异。

第一张图片:专业十六进制编辑器。

专业十六进制编辑器

第二张图片:函数输出到备忘录。

标记值应为 255(方框字符)

谢谢。

I am using Delphi 2009.

I want to view the contents of a file (in hexadecimal) inside a memo.

I'm using this code :

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; 

When I declare variable "s" as char (i know that char goes up to 255) I get results hex values up to 65535!

When i declare variable "s" as byte or chr (0)..255, it outputs different hex values, comparing to any Hexadecimal Editor!

Why is that? How can I see the correct values?

Check images for the differences.

1st image: Professional Hex Editor.

Professional Hex Editor

2nd image: Function output to Memo.

Marked value should be 255 (box character)

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦冥 2024-11-22 05:25:24

您的 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.

Your Delphi 2009 is unicode-enabled, so Char is actually WideChar and that's a 2 byte, 16 bit unsigned value, that can have values from 0 to 65535.

You could change all your Char declarations to AnsiChar and all your String declarations to AnsiString, but that's not the way to do it. You should drop Pascal I/O in favor of modern stream-based I/O, use a TFileStream, and don't treat binary data as Char.

Console demo:

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.
万劫不复 2024-11-22 05:25:24

在 Delphi 2009 中,CharWideChar 相同,即 Unicode 字符。一个宽字符占用两个字节。您想要使用 AnsiChar。在 Delphi 2009 之前(即在 Unicode Delphi 之前),CharAnsiChar 相同。

另外,您不应该使用 ReadLn。您将该文件视为具有文本文件行结尾的文本文件!这是一个通用文件!它可能根本没有任何文本文件行结尾!

In Delphi 2009, a Char is the same thing as a WideChar, that is, a Unicode character. A wide character occupies two bytes. You want to use AnsiChar. Prior to Delphi 2009 (that is, prior to Unicode Delphi), Char was the same thing as AnsiChar.

Also, you shouldn't use ReadLn. You are treating the file as a text file with text-file line endings! This is a general file! It might not have any text-file line endings at all!

清引 2024-11-22 05:25:24

为了更容易阅读输出并且看起来更好,您可能需要使用这个简单的十六进制转储格式化程序。

HexDump 过程将内存区域转储到 TStrings 中,每行两块,每行 8 字节(十六进制)和 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;

For an easier to read output, and looking better too, you might want to use this simple hex dump formatter.

The HexDump procedure dumps an area of memory into a TStrings in lines of two chunks of 8 bytes in hex, and 16 ascii chars

example

406563686F206F66 660D0A6966206578 @echo off..if ex
69737420257E7331 5C6E756C20280D0A ist %~s1\nul (..
0D0A290D0A                        ..)..

Here is the code for the dump format function

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;

And here is a complete code example for dumping the contents of a file into a Memo field.

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;
疯了 2024-11-22 05:25:24

string 在 Delphi 2009 中是 UnicodeString。如果要使用单字节字符串,请使用 AnsiStringRawByteString

请参阅字符串类型

string is UnicodeString in Delphi 2009. If you want to use single-byte strings use AnsiString or RawByteString.

See String types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文