How to read hex .dat file convert to Ascii

nex1999
nex1999 used Ask the Experts™
on
Hello experts,

 I have some files that contain hex data I would like to convert it to ascii. I saw an example and used it to create a small sample application. But this program does not seem to write all the data correctly.

unit Main;

interface

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

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Memo2: TMemo;
   OpenDialog1: TOpenDialog;
   Button1: TButton;
   Label1: TLabel;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
   FileStream: TFileStream;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

const
 MaxBufferSize = 65536; // 64k

type
 bytearray = array[0..0] of byte;

procedure TForm1.Button1Click(Sender: TObject);
var
 Buffer: Pointer;
 BytesRead, i: LongInt;
 HexStrTemp, ASCStrTemp: String;

begin
 if OpenDialog1.Execute then
 begin
   FileStream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead or fmShareDenyNone);
   GetMem(Buffer, MaxBufferSize);
   try
     while FileStream.Position < FileStream.Size do
     begin
       BytesRead := FileStream.Read(Buffer^, MaxBufferSize);
       for i := 1 to BytesRead do
       begin
         if bytebool(i mod 16) then  // 16 items per line
         begin
           HexStrTemp := HexStrTemp + IntToHex(bytearray(Buffer^)[i-1],2) + ' ';
           AscStrTemp := AscStrTemp + chr(bytearray(Buffer^)[i-1]);
         end
         else
         begin
           HexStrTemp := HexStrTemp + IntToHex(bytearray(Buffer^)[i-1],2) + ' ';
           AscStrTemp := AscStrTemp + chr(bytearray(Buffer^)[i-1]);
           Memo1.Lines.Add(HexStrTemp);
           Memo2.Lines.Add(AscStrTemp);
           HexStrTemp := '';
           AscStrTemp := '';
         end;
       end;
     end;
   finally
     FreeMem(Buffer, MaxBufferSize);
   end;
 end;
end;

end.


------The dfm------


object Form1: TForm1
  Left = 319
  Top = 110
  Width = 682
  Height = 363
  Caption = 'Main'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 40
    Width = 88
    Height = 13
    Caption = 'Total Bytes Read :'
  end
  object Memo1: TMemo
    Left = 8
    Top = 56
    Width = 401
    Height = 273
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Fixedsys'
    Font.Style = []
    ParentFont = False
    ScrollBars = ssVertical
    TabOrder = 0
  end
  object Memo2: TMemo
    Left = 416
    Top = 56
    Width = 257
    Height = 273
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Fixedsys'
    Font.Style = []
    Lines.Strings = (
      '')
    ParentFont = False
    ScrollBars = ssVertical
    TabOrder = 1
  end
  object Button1: TButton
    Left = 8
    Top = 8
    Width = 89
    Height = 25
    Caption = 'Open File...'
    TabOrder = 2
    OnClick = Button1Click
  end
  object OpenDialog1: TOpenDialog
    Left = 640
    Top = 8
  end
end
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
//? S:=Buffer;
//Just fill S with the buffer...

Var
   N: Integer;
   MakeStr2,MakeStr: String;
   
 While Length(S)>16 Do
   Begin
      MakeStr:='';
      MakeStr2:='';
      For N:=1 to 16 Do
       Begin
         MakeStr:=MakeStr+IntToHex(Ord(S[N]),2)+' ';
         If (Ord(S[N])<$30) or (Ord(S[N])>$7E) or (Ord(S[N])=$C0) or (Ord(S[N])=$80) Then
           MakeStr2:=MakeStr2+'.'
             else
           MakeStr2:=MakeStr2+S[N];
       End;
     Form1.Richedit1.Lines.Add(MakeStr+'  '+MakeStr2);
      Delete(S,1,16);
   End;

    MakeStr:='';
    MakeStr2:='';

    For N:=1 to Length(S) Do
     Begin
      MakeStr:=MakeStr+IntToHex(Ord(S[N]),2)+' ';
       If (Ord(S[N])<$30) or (Ord(S[N])>$7E) or (Ord(S[N])=$C0) or (Ord(S[N])=$80) Then
        MakeStr2:=MakeStr2+'.'
         else
        MakeStr2:=MakeStr2+S[N];
      End;

   
    Form1.Richedit1.Lines.Add(MakeStr+'  '+MakeStr2);


//make sure the font is set to courier new when displaying the hex...  (sorry about the code, i ripped it straight out of my )
hello nex1999, here is some code that uses a TFileStream to read a file, I an confussed by you method of displaying text in asci, my method displays the asci in asci and everything else in hex

procedure TForm1.sbut_ReadHexClick(Sender: TObject);
var
FStream1: TFileStream;
AryByte1: array[0..447] of Byte;
{the TFileStream.Read with Count set to 448 bytes seems to be the fastest}
BytesRead, i, NumByte: Integer;
OutPut: String;

begin
FStream1 := TFileStream.Create('E:\Icon1.ico', fmOpenRead);
try
NumByte := 0;
repeat
BytesRead := FStream1.Read(AryByte1,SizeOf(AryByte1));
for i := 0 to High(AryByte1) do
  begin
{non standard charaters (especially #0) will cause lots of problems
so you need to filter out those charaters, This also filters out the
space charater #32, since I use it to pad the output}
  if (AryByte1[i] > 32) and (AryByte1[i] < 127) then
  OutPut := OutPut+ Chr(AryByte1[i])+' ' else
  OutPut := OutPut+'('+IntToHex(AryByte1[i], 2)+') ';
  Inc(NumByte);
  if NumByte = 16 then
    begin
    OutPut := OutPut+#13#10;
    NumByte := 0;
    end;
  end;
until BytesRead < SizeOf(AryByte1);
finally
FStream1.Free;
end;
Memo2.Text := OutPut;
end;

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hope this can be useful to you, ask questions if you need more info

Author

Commented:
craig_capel,

 What is your variable S and where does it get set or read?

Slick812,

 I got your to work and I put split the output into two strings one for hex the other ascii. If in reading the stream I find a @ character how can I make add a return character to the string? This way new records are broken up by seperation of line?

Thanks for both of your ideas.

procedure TForm1.Button2Click(Sender: TObject);
var
  FStream1: TFileStream;
  AryByte1: array[0..447] of Byte;
  BytesRead, i, NumByte: Integer;
  OutPut: String;
  Hex, Ascii : String;
begin

 if OpenDialog1.Execute then
 begin
  FStream1 := TFileStream.Create(OpenDialog1.FileName, fmOpenRead or fmShareDenyNone);
 end;
  try
    NumByte := 0;
    repeat
      BytesRead := FStream1.Read(AryByte1,SizeOf(AryByte1));
      for i := 0 to High(AryByte1) do
      begin
      if (AryByte1[i] > 32) and (AryByte1[i] < 127) then
      begin
         Ascii := Ascii + Chr(AryByte1[i])+' ';
      end
      else
      begin
         hex := hex + '('+IntToHex(AryByte1[i], 2)+') ';
      end;

      Inc(NumByte);
      if NumByte = 16 then
      begin
          OutPut := OutPut+#13#10;
          NumByte := 0;
      end;
     end;

    until BytesRead < SizeOf(AryByte1);

    finally
      FStream1.Free;
  end;

  Memo1.Text := Hex;
  Memo2.Text := Ascii;
end;
Expert Spotlight: Joe Anderson (DatabaseMX)

We’ve posted a new Expert Spotlight!  Joe Anderson (DatabaseMX) has been on Experts Exchange since 2006. Learn more about this database architect, guitar aficionado, and Microsoft MVP.

???? I read the code that you posted and it would work giving you 2 strings, one in HEX and one in ASCII (more or less). But from your statement  "If in reading the stream I find a @ character how can I make add a return character ", I see you don't have any Idea what the Number values of the "Byte" are represented by the ASCII Translation. All ASCII translations to Charaters just use a numeric value like 65 for the charater "A" and 97 for "a" and 90 for "Z" and 122 for "z" and 48 for "0" and 57 for "9" and 63 for "?" and 64 for "@" . . . . .


In your code you use

if (AryByte1[i] > 32) and (AryByte1[i] < 127) then
     begin
        Ascii := Ascii + Chr(AryByte1[i])+' ';
     end.


WHY do you use (AryByte1[i] > 32) ? ? ? I tried to tell you in my example that I left out the space charater of #32, shouldn't your code be (AryByte1[i] > 31)  ? ? ? I do not have time to type out all the ASCII Charater values for you.
You might try to find a source for them , every programmer should have a ASCII value chart. AS TO the "add a return character"- - - - What did you think the Line

OutPut := OutPut+#13#10;

does? ? so something like

if AryByte1[i] = 64 {value of @} then
Ascii := Ascii + #13#10 else
if (AryByte1[i] > 31) and (AryByte1[i] < 127) then
Ascii := Ascii + Chr(AryByte1[i]);

Author

Commented:
geez...  Yeah I guess my code knowledge is not at an expert level but you don't have to bite my head off.

-nex

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial