Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi strtohex (https://www.delphipraxis.net/93873-strtohex.html)

ReVenGer 12. Jun 2007 15:55


strtohex
 
Hi zusammen,

ich möchte eine Spielstand Datei als Hex ins Memo laden, nur bekomm ich die Umwandlung
von String zu Hex nicht so wirklich gebacken.

Ein Hex Editor zeigt mir zumindest andere Werte.

Delphi-Quellcode:
function StringToHex(s:string) : string;
var t : integer;
begin
result := ' ';
for t := 1 to length(s) do begin
if t = length(s) then
result := result + IntToHex(ord(s[t]),2)
else
result := result + IntToHex(ord(s[t]),2) + ' ';
end;
end;
mal ein Auszug aus der Datei '...ÿ..ö.üÿæ.....'

so zeigt es der Hex Editor an '0E 00 90 FF 00 00 F6 13 FC FF E6 11 10 00 00 00'

und so mein Programm '2E 2E 2E FF 2E 2E F6 2E FC FF E6 2E 2E 2E 2E 2E'

Was läuft da schief?

Bernhard Geyer 12. Jun 2007 16:04

Re: strtohex
 
Die Datei ist binär Codiert. Dann solltest Du sie mit TFileStream laden und nicht mit Strings arbeiten.

Carlo91 12. Jun 2007 16:05

Re: strtohex
 
Hi,
dein Programm macht alles richtig dein fehler ist das du den "String" den der Hex-Editor dir wieder gegeben hat in deinem programm benutzt:

Zitat:

Zitat von ReVenGer
mal ein Auszug aus der Datei '...ÿ..ö.üÿæ.....'

Das problem dabei ist das der hex-editor alle bytes die er nicht als "zeichen" wieder geben kann als . anzeigt(Hexwert: 2E).

Kurz gesagt kopiere den string nicht aus dem Hex-Editor sondern lade die datei in dein programm rein.

MfG Carlo

halinchen 12. Jun 2007 16:07

Re: strtohex
 
Für mich sieht es aus, als würdest du die Datei als String einlesen und die dann in Hex umwandeln.

Macht man das nicht mit einem FileStream, und liest Byte für Byte aus und wandelt den in Hex um?

So denke ich mir das. (Es kann natürlich auch sein, das beides geht, aber an deinem gezeigten Code sehe ich kein Fehler)
Delphi-Quellcode:
var
 fs:TFileStream;
 str : String //was am Ende Rauskommt
 i : Integer;
 b : Byte;
begin
 fs := TFileStream.Create('Datei', fm_OpenRead);
 try
    For i := 0 to fs.Size do begin
      fs.ReadBuffer(b,sizeof (b));
      //oder fs.ReadByte(b); <-- bin mir nichtt sicher
      str := Str + '|' + IntToHex(b,2); <-- '|' ist der Trenner
    end;
 finally
 fs.Free;
 end;
end;
ungetestet

[edit] Hmm... Zum 1. Mal kein roter Kasten... [/edit]

ErazerZ 12. Jun 2007 16:08

Re: strtohex
 
Nunja, deine Funktion ist in Ordnung. Nur dein String ist einwenig nicht in Ordnung weil die punkte sind in Hex 0x2E, der HexEditor kann diese Zeichen einfach nicht darstellen.
Z.B.:
Delphi-Quellcode:
  showmessage(stringtohex('hi was geht?'#0#12#13#14#0'wieder ich!'));
Siehst gleich das die anderen Bytes angezeigt werden.

halinchen 12. Jun 2007 16:12

Re: strtohex
 
Zitat:

Zitat von Carlo91
Das problem dabei ist das der hex-editor alle bytes die er nicht als "zeichen" wieder geben kann als . anzeigt(Hexwert: 2E).

Aber wenn der das Zeichen nicht kennt (z.B. #13) dann zeigt er einen Punkt im Textmodus an. Aber ein normaler Hex-Editor sollte doch dann dort wo er die Daten als Hex anzeigt die 13 als Hex anzeigen, oder?

[edit] Ich habs jetzt kapiert, was du meinst. Da stand wer auf meiner Internetleitung :mrgreen: [/edit]

Carlo91 12. Jun 2007 16:14

Re: strtohex
 
Ja sollte angezeigt werden warum auch nicht lol?

Der_Unwissende 12. Jun 2007 16:15

Re: strtohex
 
Zitat:

Zitat von halinchen
Delphi-Quellcode:
    For i := 0 to fs.Size do begin
      fs.Read(b,sizeof (b));
      //oder fs.ReadByte(b); <-- bin mir nichtt sicher
      str := Str + '|' + IntToHex(b,2); <-- '|' ist der Trenner
    end;

Hi,
an sich sollte der hier gepostete Weg auf jeden Fall funktionieren. Wenn Du das so machst, solltest Du jedoch noch besser noch mit einem kleinen Puffer arbeiten. In diesem Fall liest Du jedes Byte einzeln in der Schleife ein, dass dauert und dauert und dauert. Viel schneller geht es, wenn Du gleich einen ganzen Haufen Bytes in ein Array liest und die dann in einem Rutsch bearbeitest.
Delphi-Quellcode:
var buffer: TByteDynArray;
    readBytes: Integer;
// wie gehabt!
...
begin
  // 1024 Byte Puffer
  setLength(buffer, 1024);
// wie gehabt!
...
  readBytes := fs.Readbuffer(buffer[0], length(buffer));
  while readBytes > 0 do
  begin
    for i := 0 to readBytes - 1 do
    begin  
      str := Str + '|' + IntToHex(buffer[i],2); <-- '|' ist der Trenner
    end;
  end;
Auch das mit dem String kann man noch effizienter machen, indem man hier für jedes Zeichen im Puffer (readBytes) einfach je 3 Byte (2 Byte Hex-Wert + 1 Byte Trenner) alloziert und dann direkt am richtigen Index einfügt.

Gruß Der Unwissende

[edit]
Fehler korrigiert, muss natürlich read und nicht readBuffer sein! Danke @halinchen!
[/edit]

halinchen 12. Jun 2007 16:20

Re: strtohex
 
@Der_Unwissende: Schon klar, das meine Lösung nicht optimal ist. Wie immer :mrgreen:. Nein Spaß bei Seite. Sollte ja nur ein Anschauungsmaterial sein.

Allerdings nahm bei mir mal ReadBuffer bei einem älteren Projekt keine variablen Arrays an. Gleich nochmal testen und lernen :coder2:
[edit] oh, sry. das war ja Carlo91 und war auch keine Frage... :wall: [/edit]
@ReVenGer: Du sollst die Daten nicht aus dem Hex-Editor kopieren, sondern selber die Datei einlesen. Den sonst ist dort wo z.B #13 steht in deinem Programm ein Punkt. Sprich: Beide Programme arbeiten mit unterschiedlichem Ausgangsmaterial.

ReVenGer 12. Jun 2007 16:23

Re: strtohex
 
ahhhhhhhhh.... *klick*

erstmal danke für die schnellen antworten!
ich habe fälschlicherweise angenommen, das er das nur nicht anzeigen kann,
aber den tatsächlichen wert übernimmt.

super, dann kann ich ja auch gezielt nach bytes suchen und diese verändern.

speichern sollte genau rückwärts erfolgen richtig?

Der_Unwissende 12. Jun 2007 16:26

Re: strtohex
 
Zitat:

Zitat von halinchen
@Der_Unwissende: Schon klar, das meine Lösung nicht optimal ist. Wie immer :mrgreen:. Nein Spaß bei Seite. Sollte ja nur ein Anschauungsmaterial sein.

Schon klar, hab auch gerade noch einen Fehler korrigiert (den ich gemacht habe, ReadBuffer hat keinen Rückgabewert). Wollte es nur kurz erwähnen, da es eben funktionieren würde und schon bei einer Datei von > 1 MByte in echt langes Warten ausarten dürfte. Da kommt sonst schnell die Frage, wie man das denn schneller tun könnte.
Bei meinem ersten Programm, dass da mal größere Dateien (> 100 MByte) öffnen musste war das dann der Unterschied zwischen 1 Minute Ladezeit und < 1 Sekunde. Waren dann noch ein zwei andere Stellen, wo ich das Speicherkopieren in Schleifen durch Move ersetzt habe, macht natürlich einiges aus!

ReVenGer 12. Jun 2007 16:51

Re: strtohex
 
Ich hab da wohl noch nen denkfehler drin.

Delphi-Quellcode:
function StringToHex(str :string) : string;
var
fs:TFileStream;
i : Integer;
b : Byte;
begin
fs := TFileStream.Create('test.gam', fmOpenRead);
try
    For i := 0 to fs.Size do begin
      fs.ReadBuffer(b,sizeof (b));
      //oder fs.ReadByte(b); <-- bin mir nichtt sicher
      str := Str + '|' + IntToHex(b,2);
    end;
finally
fs.Free;
end;
end;
und aufgerufen wird es so

Delphi-Quellcode:
label3.caption:=stringtohex(str);

war jetzt nur damit es schnell geht nen label.
die datei die ich einlese hat nur 30kB.
von daher nichts großes, deshalb habe ich mich auhc für die kleine variante entschieden.


aber das programm erzeugt einen error.

halinchen 12. Jun 2007 16:57

Re: strtohex
 
Delphi-Quellcode:
function StringToHex : string;
var
fs:TFileStream;
i : Integer;
b : Byte;
begin
result := '';
fs := TFileStream.Create('test.gam', fmOpenRead);
try
    For i := 0 to fs.Size do begin
      fs.ReadBuffer(b,sizeof (b));
      //oder fs.ReadByte(b); <-- bin mir nichtt sicher
      result := result + '|' + IntToHex(b,2);
    end;
finally
fs.Free;
end;
end;
Allerdings solltest du dir bewusstsein, das es vielleicht besser ist, den Spielstand immer im Speicher zu haben (z.B als TMemoryStream). Den sonst musst du dich so blöd mit dem Trennstrich rumärgern.

ErazerZ 12. Jun 2007 17:02

Re: strtohex
 
Delphi-Quellcode:
var
  fs: TFileStream;
  lpBuffer: array of Byte;
  // temporär
  s: string;
  x: Integer;
begin
  // entweder so, oder du ließt es in Blöcken aus und parst sie schon gleich ...
  fs := TFileStream.Create('c:\tmp.txt', fmOpenRead);
  try
    if (fs.Size > 0) then
    begin
      SetLength(lpBuffer, fs.Size);
      fs.Read(lpBuffer[0], fs.Size);
    end;
  finally
    fs.Free;
  end;

  // brauchst nicht - nur ausgabe
  s := '';
  for x := Low(lpBuffer) to High(lpBuffer) do
  begin
    s := s + IntToHex(lpBuffer[x], 2) + ' ';
  end;
  ShowMessage(s);

ReVenGer 12. Jun 2007 17:05

Re: strtohex
 
Bekomme immer die meldung 'incompatible types intger and string"

halinchen 12. Jun 2007 17:12

Re: strtohex
 
Zitat:

Zitat von ReVenGer
Bekomme immer die meldung 'incompatible types intger and string"

an welcher Stelle?

[edit] ich hab jeden Code ausprobiert. Bei mir gehen alle[/edit]

ReVenGer 12. Jun 2007 17:20

Re: strtohex
 
bei der übergabe zum memo,label, etc.

wie rufst du denn die function auf?

ReVenGer 12. Jun 2007 20:22

Re: strtohex
 
bei der übergabe zum memo,label, etc.

wie rufst du denn die function auf?

Klaus01 12. Jun 2007 20:38

Re: strtohex
 
Dann zeige uns doch einmal wie Du es jetzt hast?
So ist nur raten angesagt.

Grüße
Klaus

ReVenGer 12. Jun 2007 20:45

Re: strtohex
 
jetzt hab ich nen streamread error.. ich bau das jetzt nochmal komplett um.

ReVenGer 12. Jun 2007 21:39

Re: strtohex
 
Delphi-Quellcode:
Procedure stringtohex;
var
  fs: TFileStream;
  lpBuffer: array of Byte;
  s: string;
  x: Integer;
 begin
   fs := TFileStream.Create('test.gam', fmOpenRead);
  try
    if (fs.Size > 0) then
    begin
      SetLength(lpBuffer, fs.Size);
      fs.Read(lpBuffer[0], fs.Size);
    end;
    s := '';
  for x := Low(lpBuffer) to High(lpBuffer) do
  begin
    s := s + IntToHex(lpBuffer[x], 2) + ' ';
  end;
   Memo1.Lines.Add(s);
  finally
    fs.Free;
  end;
 end;
Wenn mir das jetzt nochmal einer erklären könnte habt ihr mich glücklich gemacht.

[Error] Unit2.pas(71): Undeclared identifier: 'Memo1'
[Error] Unit2.pas(71): Missing operator or semicolon
[Fatal Error] Project1.dpr(6): Could not compile used unit 'Unit2.pas'

Verstehe das nicht,warumdas mit showmessage geht, aber das memo nicht finden kann.

marabu 13. Jun 2007 06:10

Re: strtohex
 
Guten Morgen.

StrToHex() ist bei dir eine unabhängige Prozedur und keine Methode der Form. Das ist auch richtig so, aber du kannst aus dieser Prozedur nicht auf Eigenschaften der Form (z.B. Memo1) zugreifen. Alle Ein- und Ausgaben deiner Prozedur sollten über entsprechende Parameter gesteuert werden.

Eine sinnvolle Signatur wäre:

Delphi-Quellcode:
procedure HexDump(const fn: TFileName; s: TStrings);
Ein Aufruf könnte so aussehen: HexDump('C:\highscore.dat', Memo.Lines);

Für die Konvertierung von Bytes in ihre Hex-Darstellung gibt es die Funktion BinToHex().

Grüße vom marabu

ReVenGer 13. Jun 2007 06:31

Re: strtohex
 
danke erstmal für die antwort,
aber wenn ich es so aufrufe, bekomme ich den undeclared identifier opendialog1.

Delphi-Quellcode:
stringtohex(OpenDialog1.FileName, Memo1.Lines.add);

marabu 13. Jun 2007 07:59

Re: strtohex
 
Vermutlich hast du an der Stelle, an der du den Aufruf von StrToHex() machst, keinen Zugriff auf OpenDialog1. Kannst du den Aufruf mal in seinem Kontext zeigen?

ReVenGer 13. Jun 2007 08:40

Re: strtohex
 
Ich hätte bei Assembler bleiben sollen :)

Delphi-Quellcode:
Procedure stringtohex(const fn: TFileName; sg: tStrings);
var
  fs: TFileStream;
  lpBuffer: array of Byte;
  x: Integer;
  s: string;
 begin
   fs := TFileStream.Create('test.gam', fmOpenRead);
  try
    if (fs.Size > 0) then
    begin
      SetLength(lpBuffer, fs.Size);
      fs.Read(lpBuffer[0], fs.Size);
    end;
    s := '';
  for x := Low(lpBuffer) to High(lpBuffer) do
  begin
    s := s + IntToHex(lpBuffer[x], 2) + ' ';
   end;
  // showmessage(s);
       finally
    fs.Free;
  end;
  end;


procedure TForm2.N3Click(Sender: TObject);
begin
 opendialog1.execute;
 HexDump(OpenDialog.FileName, Memo.Lines);
 //showmessage(opendialog1.filename);   //Pfad
end;

Klaus01 13. Jun 2007 08:42

Re: strtohex
 
Delphi-Quellcode:
HexDump(OpenDialog1.FileName, Memo.Lines);
sollte es nicht openDialog1 heißen und nicht openDialog?

Grüße
Klaus

ReVenGer 13. Jun 2007 08:48

Re: strtohex
 
sorry, hatte ich hinterher korrigiert.
trotzdem sagt er mir undeclared identifier.

ich versteh das nicht, in assembler konnte ich immer direkt auf sachen zugreifen, ohne umwege.

marabu 13. Jun 2007 08:50

Re: strtohex
 
Manchmal möchte man den OpenDialog abbrechen:

Delphi-Quellcode:
procedure TForm2.N3Click(Sender: TObject);
begin
  with OpenDialog1 do
    if Execute then
      StrToHex(FileName, Memo.Lines);
end;
Freundliche Grüße

halinchen 13. Jun 2007 14:14

Re: strtohex
 
Zitat:

Zitat von ReVenGer
trotzdem sagt er mir undeclared identifier.

Und du bist dir sicher, das es den auch wirklich gibt? Eventuell hast du ihn gelöscht oder umbenannt.

marabu 13. Jun 2007 16:51

Re: strtohex
 
Hallo,

ich vermute, dass die Komponente OpenDialog1 auf einer anderen Form als Form2 zu finden ist. Falls sich OpenDialog1 auf Form1 befindet, dann musst du deinen Quellcode so abändern:

Delphi-Quellcode:
procedure TForm2.N3Click(Sender: TObject);
begin
  with Form1.OpenDialog1 do
    if Execute then
      StrToHex(FileName, Memo.Lines);
end;
Damit würde dann dein Code übersetzt, aber elegant ist das nicht. Da du aber noch schwer mit Delphi kämpfst, bringt es dir zumindest eine "schnelles" Erfolgserlebnis. Pascal und seine Nachkommen sind block-orientierte Sprachen und die Variablen haben einen Gültigkeitsbereich. Lies zu diesem Thema in der Online-Hilfe das Topic "Delphi Sprachreferenz | Syntaktische Elemente | Blöcke und Gültigkeitsbereich" und du findest bestimmt einen Einstieg.

Grüße vom marabu

ReVenGer 13. Jun 2007 18:56

Re: strtohex
 
also ich habe noch immer das problem mit udeclared identifier.

egal was ich mache, ob ich nen komplett neues projekt nehme (hatte vermutet das beim alten was verbogen war) oder ich in meiner source die sachen verändere, ich bekomme den stream nicht in mein memo.

halinchen 13. Jun 2007 19:07

Re: strtohex
 
Häng doch bitte mal dein Projekt als Anhang an.

[edit] Oder, wenn es zu groß ist: Du sagtest, das es mit einem neuen Projekt auch nicht geht. Dann kannst du das anhängen [/edit]

ReVenGer 13. Jun 2007 19:12

Re: strtohex
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal die Source.
Bin echt am verzweifeln, weil er ja den schowmessage dialog aufruft.

nur das memo nicht

halinchen 13. Jun 2007 20:43

Re: strtohex
 
Bei mir gehts. Es zeigt in einer MessageBox die Hex-Dinger an. Aber von einem Memo sehe ich weit und breit nichts.
Du musst schon irgentwo auf der Form ein Memo anlegen. Wenn ich eins auf die Form ziehe und dann das Programm starte gehts auch mit Memo.

Im Übrigen:
Delphi-Quellcode:
Form2.Memo1.Lines.Add(s)
Form2 muss mit davor wenns auf Form2 ist.

Klaus01 13. Jun 2007 20:45

Re: strtohex
 
Mal eine ganz dumme Frage, auf welcher Form soll denn das memo1 sein.
Habe keines gefunden.

Grüße
Klaus

ReVenGer 13. Jun 2007 20:53

Re: strtohex
 
jetzt gehts bei mir auch :wall:

ich danke euch, hab vor lauter editieren und verändern komplett die übersicht verloren.

oh man... es gibt tage da verliert man, und tage, da gewinnen die anderen...


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:24 Uhr.

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