Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Hex-Darstellung einer binären Datei (https://www.delphipraxis.net/23930-hex-darstellung-einer-binaeren-datei.html)

Luckie 12. Jun 2004 10:23


Hex-Darstellung einer binären Datei
 
So stelle ich eine binäre Datei hexadezimal dar:
Delphi-Quellcode:
type
  TMyByteArray = array of byte;

const
  HEXWIDTH = 2;
  BUFFERSIZE = 8;

function BuffToHex(ByteArray: TMyByteArray): string;
var
  i: Integer;
  s: String;
  foo: string;
begin
  Setlength(foo, length(ByteArray) * (HEXWIDTH+2));
  for i := 0 to length(ByteArray) - 1 do
  begin
    s := '$'+IntToHex(ord(ByteArray[i]), HEXWIDTH) + ' ';
    Move(s[1], foo[i * (HEXWIDTH+2) + 1], length(s));
  end;
  result := foo;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFileStream;
  Buffer: TMyByteArray;
  BytesRead: Longint;
  s: String;
  i: Int64;
begin
  i := 0;
  SetLength(Buffer, BUFFERSIZE);
  fs := TFileStream.Create('G:\MP3s\Beatles\Beatles -  Blue Jay Way.mp3',
    fmOpenRead);
  SetLength(s, fs.size*(HEXWIDTH+2));
  Progressbar1.Max := fs.Size div BUFFERSIZE;
  try
    repeat
      BytesRead := fs.Read(Buffer[0], BUFFERSIZE);
      Move(BuffToHex(Buffer)[1], s[i*(HEXWIDTH+2)+1], 10);
      Inc(i);
      Progressbar1.StepIt;
      Application.ProcessMessages;
    until BytesRead < BUFFERSIZE;
    Memo1.Text := s;
  finally
    FreeAndNil(fs);
  end;
end;
Jetzt habe ich aber festgestellt, das je nach Buffergröße die Datei anders aussieht. :roll: Wo ist da mein Denkfehler im Code? ich finde hin einfach nicht.

Christian Seehase 12. Jun 2004 12:47

Re: He darstellung einer binären Datei
 
Moin Luckie,

wenn ich das richtig sehe ist das Problem hier:

Code:
Move(BuffToHex(Buffer)[1], s[i*(HEXWIDTH+2)+1], [b][color=red]10[/color][/b]);
das sollte wohl besser in Abhängigkeit der Buffergrösse passieren.

Luckie 12. Jun 2004 14:16

Re: He darstellung einer binären Datei
 
Hm. Danke. Das muss auf alle Fälle auch angepast werden. Am Verhalten hat sich allerdings nichts geändert.

Muetze1 12. Jun 2004 15:52

Re: He darstellung einer binären Datei
 
Moin!

Sag mal Luckie, ich bin irgendwie auch ein wenig enttäuscht von dir mit diesen Fragen ...

Du berechnest den Zielindex in s falsch in deiner Schleife, weil du (HEXWIDTH+2)+1 nimmst als Granularität. Diese gilt aber nur für ein Hexzeichen umgewandelt in "$xx ", aber deine BuffToHex wandelt / baut einen String auf, der BUFFERSIZE - oft einen solchen String hat, somit zeigst du abhängig von deiner BufferSize immer nur das erste HexByte der Buffergranularität an - und deshalb ändert sich das auch immer mit der BUFFERSIZE...

MfG
Muetze1

Luckie 12. Jun 2004 16:03

Re: He darstellung einer binären Datei
 
Ich bin im Moment etwas vernagelt. Was meinst du jetzt?
Zitat:

Diese gilt aber nur für ein Hexzeichen umgewandelt in "$xx ", aber deine BuffToHex wandelt / baut einen String auf, der BUFFERSIZE - oft einen solchen String hat
Fehlt da nicht irgendwo ein Wort zum Schluss. Ich ahne, was du mir sagen willst, aber ich stehe zur Zeit irgendwie auf dem Schlauch. :wall:

Muetze1 12. Jun 2004 16:11

Re: Hex-Darstellung einer binären Datei
 
Moin!

:shock:

Delphi-Quellcode:
type
  TMyByteArray = array of byte;

const
  HEXWIDTH = 2;
  BUFFERSIZE = 8;

function BuffToHex(ByteArray: TMyByteArray): string;
var
  i: Integer;
  s: String;
  foo: string;
begin
  Setlength(foo, length(ByteArray) * (HEXWIDTH+2));
  for i := 0 to length(ByteArray) - 1 do
  begin
    s := '$'+IntToHex(ord(ByteArray[i]), HEXWIDTH) + ' ';
    Move(s[1], foo[i * (HEXWIDTH+2) + 1], length(s));
  end;
  result := foo;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFileStream;
  Buffer: TMyByteArray;
  BytesRead: Longint;
  s: String;
  i: Int64;
begin
  i := 0;
  SetLength(Buffer, BUFFERSIZE);
  fs := TFileStream.Create('G:\MP3s\Beatles\Beatles -  Blue Jay Way.mp3',
    fmOpenRead);
  SetLength(s, fs.size*(HEXWIDTH+2));
  Progressbar1.Max := fs.Size div BUFFERSIZE;
  try
    repeat
      BytesRead := fs.Read(Buffer[0], BUFFERSIZE);
      Move(BuffToHex(Buffer)[1], s[i*((HEXWIDTH+2)*BUFFERSIZE)+1], (HEXWIDTH+2)*BUFFERSIZE);
      Inc(i);
      Progressbar1.StepIt;
      Application.ProcessMessages;
    until BytesRead < BUFFERSIZE;
    Memo1.Text := s;
  finally
    FreeAndNil(fs);
  end;
end;
/EDIT: Die Grösse beim Move() musste auch noch angepasst werden...

MfG
Muetze1

Luckie 12. Jun 2004 16:23

Re: Hex-Darstellung einer binären Datei
 
Ach das meist du. Jetzt geht es - fast. Die Werte scheinen jetzt identsich zu sein bei verschiedenen Buffer Größen, nur bekomme ich eine Exception zum Schlus: Invalid pointer operation. ich hasse diese Rumgeschubse im Speicher.

Edit: Nicht * BUFFERSIZE, sondern mal bytesRead muss es heißen, weil zum Scvhluss kann es ja sein, dass er weniger liest.

Jetzt nur noch ein Problem: Der Anfang stimmt mit einem Hexeditor über ein, nur das Ende nicht.

Tryer 13. Jun 2004 12:29

Re: Hex-Darstellung einer binären Datei
 
Ich habe keinen Unterschied zwischen der folgenden Variante und einem HexEditor (TextPad / UltraEdit) entdeckt:

Delphi-Quellcode:
type
  TMyByteArray = array of Byte;

const
  HEXPREFIX = '$';
  HEXSUFFIX = ' ';
  BUFFERSIZE = $FFFF;

procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFileStream;
  Buffer: TMyByteArray;
  BytesRead: Longint;
  s: String;
  i: Int64;
  HexLength: Integer;
  Startzeit: LongInt;

  function BuffToHex2(ByteArray: TMyByteArray): string;
  var
    i: Integer;
    s: string;
    foo: string;
  const
    HEXSTR = '0123456789ABCDEF';
  begin
    SetLength(foo, Length(ByteArray) * HexLength);
    for i := 0 to High(ByteArray) do
    begin
      s := HEXPREFIX + HEXSTR[((ByteArray[i] and $F0) shr 4) + 1] +
        HEXSTR[(ByteArray[i] and $0F) + 1] + HEXSUFFIX;
      Move(s[1], foo[i * HexLength + 1], HexLength);
    end;
    Result := foo;
  end;

begin
  if OpenDialog1.Execute then
  begin
    HexLength := Length(HEXPREFIX) + 2 + Length(HEXSUFFIX);
    i := 0;
    Memo1.Clear;
    fs := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    SetLength(s, fs.Size * HexLength);
    SetLength(Buffer, BUFFERSIZE);
    ProgressBar1.Max := fs.Size;
    try
      Startzeit := GetTickCount;
      repeat
        BytesRead := fs.Read(Buffer[0], BUFFERSIZE);
        Move(BuffToHex2(Buffer)[1], s[i * (HexLength * BUFFERSIZE) + 1],
          HexLength * BytesRead);
        Inc(i);
        ProgressBar1.StepBy(BytesRead);
        Application.ProcessMessages;
      until (BytesRead < BUFFERSIZE) or (GetKeystate(VK_ESCAPE) < 0);
      Caption := FloatToStr((GetTickCount - Startzeit) / 1000);
    finally
      FreeAndNil(fs);
    end;
    if BytesRead < BufferSize then
      Memo1.Text := s
    else
      Progressbar1.Position := 0;
  end;
end;
Das IntToHex hab ich ersetzt, dieses nutzt FmtStr() und hat dadurch einen zimlichen Overhead.
Da Du eh Byteweise arbeitest ist das Ergebniss jeweils auf 2 Hexzeichen begrenzt und andere Darstellungen lassen sich auch durch ein anderes Prefix (z.B. '$00') erreichen.
ProgressBar1.Max auf fs.Size und ein StepBy(BytesRead) sorgen dafür das am Ende kein "Überlauf" entsteht.

MfG,
Tryer


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:22 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz