Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hex view of a file

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.

like image 799
Panos Kal. Avatar asked Nov 27 '22 12:11

Panos Kal.


2 Answers

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.
like image 140
Cosmin Prund Avatar answered Dec 11 '22 01:12

Cosmin Prund


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!

like image 42
Andreas Rejbrand Avatar answered Dec 11 '22 01:12

Andreas Rejbrand