Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   String zu Byte-Array konvertieren und umgekehrt (https://www.delphipraxis.net/195649-string-zu-byte-array-konvertieren-und-umgekehrt.html)

knaeuel 15. Mär 2018 12:10

String zu Byte-Array konvertieren und umgekehrt
 
Hallo zusammen, ich habe folgendes Problem:

Ich muss für einen an sich recht simplen späteren Vorgang Strings zu Byte-Arrays konvertieren und umgekehrt. Die Umwandlung muss auf den 3 Plattformen Windows, iOS und Android dieselben Ergebnisse liefern - und genau da liegt der Knackpunkt.

Auf Windows funktioniert das problemlos, ich konvertiere Text zu Bytes und wieder zurück und habe wieder den Ausgangstext vorliegen.
Auf Android und iOS wandle ich den Text in Bytes um -> bis hierhin stimmen die Daten mit dem Windows-System überein - aber die Rückumwandlung liefert einen völlig anderen String, übrigens auf Android und iOS identisch.

konkretes Beispiel:
String:
"12345678 einszwo"

Wandlung zu Byte-Array liefert:
$31 $32 $33 $34 $35 $36 $37 $38 $20 $65 $69 $6E $73 $7A $77 $6F

Rückumwandlung auf iOS und Android liefert:
aus Delphi-Debugger kopiert: "#003#023'#3CScs'#202#006'V'#226'ç7§v'"
optische Abtipp-Kopie: " #3CScs_ V_ç7§v"
(die beiden _ sind eigentlich viereckige Kästchen mit Kreuzchen drin)

Folgende functions setze ich zur Wandlung ein (Aufruf folgt weiter unten):
Delphi-Quellcode:
//wandelt ein byte-array in hex-text um, 2 zeichen je byte
function TForm1.bytearray2HexString(input:array of byte):string;
var einhexbyte:string;
    i:integer;
begin
  result:='';
  for i:=0 to length(input)-1 do
  begin
    einhexbyte:=Format('%x',[input[i]]);
    if length(einhexbyte)=1 then
      einhexbyte:='0'+einhexbyte;
    result:=result+einhexbyte;
  end;
end;

function TForm1.TxtString2HexString(s:string):string;
var p,i:integer;
    hilfsar:array of byte;
begin
  //soll Text in die jeweiligen Hex-Zeichencodes übersetzen
  //und aus den Zeichencodes einen neuen String als result basteln
  //Zeichenweise durch den Quellstring laufen
  //und dabei zunächst als Byte-Array speichern
  setlength(hilfsar,0);
{$IFDEF MSWINDOWS}
  for i:=1 to length(s) do
{$ELSE} //auf iOS und Android sind die Strings 0-basiert...
  for i:=0 to length(s)-1 do
{$ENDIF}
  begin
    //in byte-array schreiben
    p:=length(hilfsar);
    setlength(hilfsar,p+1);
    hilfsar[p]:=ord(s[i]);
  end;
  //anschließend bytearray2HexString aufrufen - fertig
  result:=bytearray2HexString(hilfsar);
end;

function TForm1.HexStringToByteArray(input:string):System.TArray<System.Byte>;
var i,p:integer;
begin
  //immer 2 Zeichen nehmen und zum Hexwert machen
  setlength(result,0);
{$IFDEF MSWINDOWS}
  for i:=1 to length(input) do
{$ELSE} //auf iOS und Android sind die Strings 0-basiert...
  for i:=0 to length(input)-1 do
{$ENDIF}
  begin
    if i mod 2 = 0 then
    begin
      p:=length(result);
      setlength(result,p+1);
      result[p]:=TwoHexCharsToInt(input[i-1],input[i]);
    end;
  end;
end;

//wandelt eine als String gespeicherte Hexadezimalzahl in eine Dezimalzahl
//und speichert sie im Result
function TForm1.TwoHexCharsToInt(charhigh,charlow:char):integer;
begin
  result:=0;
  case charhigh of
  '0': result:=16*0;
  '1': result:=16*1;
  '2': result:=16*2;
  '3': result:=16*3;
  '4': result:=16*4;
  '5': result:=16*5;
  '6': result:=16*6;
  '7': result:=16*7;
  '8': result:=16*8;
  '9': result:=16*9;
  'A','a': result:=16*10;
  'B','b': result:=16*11;
  'C','c': result:=16*12;
  'D','d': result:=16*13;
  'E','e': result:=16*14;
  'F','f': result:=16*15;
  end;
  case charlow of
  '0': result:=result+0;
  '1': result:=result+1;
  '2': result:=result+2;
  '3': result:=result+3;
  '4': result:=result+4;
  '5': result:=result+5;
  '6': result:=result+6;
  '7': result:=result+7;
  '8': result:=result+8;
  '9': result:=result+9;
  'A','a': result:=result+10;
  'B','b': result:=result+11;
  'C','c': result:=result+12;
  'D','d': result:=result+13;
  'E','e': result:=result+14;
  'F','f': result:=result+15;
  end;
end;

function TForm1.TranslateToText(input:array of byte):string;
var i:integer;
begin
  result:='';
  for i:=0 to length(input)-1 do
    result:=result+chr(input[i]);
end;
Der Aufruf zur Wandlung vom Text zum Bytearray sieht so aus:
(das Byte-Array existiert nur kurz und wird dann in einen String umgeschrieben: z.B. aus 2 Bytes $0B $A1 würde der String "0BA1")
Delphi-Quellcode:
var ursprungstext,hexstring:string;

//Wandlung: String -> Hex-String (aus Byte-Array)
ursprungstext:='12345678 einszwo';
hexstring:=TxtString2HexString(ursprungstext);

//Wandlung: Byte-Array (aus Hex-String) -> String
ursprungstext:=TranslateToText(HexStringToByteArray(hexstring));
Ich verstehe nicht, wie die Übersetzung vorwärts und rückwärts unterschiedliche Ergebnisse liefern kann? Wo liegt mein (Denk-)Fehler? :coder2: Ich bin für jede Hilfe dankbar!

Wie bekomme ich Android und iOS dazu, dieselben Ergebnisse zu liefern, wie Windows?

himitsu 15. Mär 2018 12:18

AW: String zu Byte-Array konvertieren und umgekehrt
 
Erstmal, in Android/iOS fängt String bei 0 an.

http://docwiki.embarcadero.com/RADSt...trings_(Delphi)
http://docwiki.embarcadero.com/RADSt...-Typen_(Delphi)

Low(string) = 0 auf Android/iOS
Low(string) = 1 auf Windows

[edit]
Upss, schon beachtet, aber Low() statt IFDFF ist bestimmt schöner.

Daniel 15. Mär 2018 12:23

AW: String zu Byte-Array konvertieren und umgekehrt
 
TEncoding.GetBytes() ?
Funktioniert plattform-übergreifend und ist seit einigen Delphi-Versionen mit dabei.

himitsu 15. Mär 2018 12:29

AW: String zu Byte-Array konvertieren und umgekehrt
 
Zitat:

Delphi-Quellcode:
{$IFDEF MSWINDOWS}
  for i:=1 to length(input) do
{$ELSE} //auf iOS und Android sind die Strings 0-basiert...
  for i:=0 to length(input)-1 do
{$ENDIF}
if i mod 2 = 0 then

=0 ... je nach String-Typ ist der Vergleich auf den Systemen unterschiedlich.
Jeweils das erste Zeichen oder das zweite Zeichen. :zwinker:


Vorschlag:
Mit TEncoding.Default den String in ein TBytes (ANSI) und das dann z.B. via BinToHex nach HEX.
Andersrum HexToBin und dann via TEncoding.Default von TBytes nach String.


Zitat:

Delphi-Quellcode:
if length(einhexbyte)=1 then
      einhexbyte:='0'+einhexbyte;

Format kennt auch führende Nullen, siehe OH.

knaeuel 15. Mär 2018 14:55

AW: String zu Byte-Array konvertieren und umgekehrt
 
Danke schon mal für die Antworten!

Ich probiere mich mal mit "TEncoding.GetBytes()" :)

knaeuel 15. Mär 2018 15:46

AW: String zu Byte-Array konvertieren und umgekehrt
 
ich hab noch einen Fehler gefunden, der das Problem löst...

dieses Code-Fragment:
Delphi-Quellcode:
{$IFDEF MSWINDOWS}
  for i:=1 to length(input) do
{$ELSE} //auf iOS und Android sind die Strings 0-basiert...
  for i:=0 to length(input)-1 do
{$ENDIF}
  begin
    if i mod 2 = 0 then
sollte so aussehen:
Delphi-Quellcode:
{$IFDEF MSWINDOWS}
  for i:=1 to length(input) do
  begin
    if i mod 2 = 0 then
{$ELSE} //auf iOS und Android sind die Strings 0-basiert...
  for i:=0 to length(input)-1 do
  begin
    if (i+1) mod 2 = 0 then
{$ENDIF}

himitsu 15. Mär 2018 17:31

AW: String zu Byte-Array konvertieren und umgekehrt
 
Hatte ich zwar schon genannt und wenn man das dann auch noch alles umsetzt, dann kommt in etwa sowas bei raus
Delphi-Quellcode:
for i := Low(string) to High(input) do
begin
  if i mod 2 <> Low(string) then


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:33 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