![]() |
Hex to Base64
Hey Leute,
ich durchsuche seit gestern Nacht das Internet nach etwas Brauchbaren, wurde aber leider nicht fündig. Ich habe derzeit folgendes Problem: Ich möchte einen Hex-Wert (02 01 AA B6 00 00) mit Base64 codieren. Das Ergebnis sollte in diesem Falle "AgGqtgAA" sein. Ich gebe auch offen zu, dass ich nicht genau weiß, was Base64 überhaupt ist. Die Wikipedia Seite dazu habe ich mir schon durchgelesen, bin aber leider nicht in der Lage selbst eine Funktion dafür zu schreiben. Ich habe u.A. herausgefunden, dass das mit irgendeiner Indy Komponente gehen soll, gefunden habe ich diese aber nicht. Ich wäre euch wirklich sehr dankbar, wenn ihr mir bei meinem Problem helfen könnt. Wichtig ist, dass der Hex-Wert derzeit im Stringformat vorliegt, das könnte man allerdings ändern :) |
AW: Hex to Base64
Indy enthält Klassen für Base64
Delphi-Quellcode:
(siehe
uses
..., IdCoder, IdCoderMIME; var Bytes: TIdBytes; Base64String: String; begin //... Bytes := ...; // array of bytes //... Base64String := TIdEncoderMIME.EncodeBytes(Bytes); //... Bytes := TIdDecoderMIME.DecodeBytes(Base64String); //... end; ![]() Man kodiert allerdings nie "Hex Werte" sondern 8 Bit Binärdaten nach ![]() |
AW: Hex to Base64
Liste der Anhänge anzeigen (Anzahl: 1)
vielleicht hilft Dir der Anhang weiter
Gruß K-H |
AW: Hex to Base64
Wenn Du nicht eine der Base64/Mime-Funktionen zur Verfügung hast, kann man auch mit Bordmitteln arbeiten. Das Program unten liefert die Ausgabe AgGqtgAA
Delphi-Quellcode:
program b64;
{$apptype console} const CT64: array[0..63] of ansichar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; {---------------------------------------------------------------------------} function Base64Str(psrc: pointer; L: integer): ansistring; {-Base64 string of memory block of length L pointed by psrc} var q,r: integer; b0,b1,b2: byte; type pByte = ^byte; begin result := ''; if (L>0) and (psrc<>nil) then begin q := L div 3; r := L mod 3; while q>0 do begin b0 := pByte(psrc)^; inc(pByte(psrc)); b1 := pByte(psrc)^; inc(pByte(psrc)); b2 := pByte(psrc)^; inc(pByte(psrc)); result := result + CT64[(b0 shr 2) and $3f] + CT64[((b0 shl 4) and $30) or ((b1 shr 4) and $0f)] + CT64[((b1 shl 2) and $3c) or ((b2 shr 6) and $03)] + CT64[b2 and $3f]; dec(q); end; if r=2 then begin b0 := pByte(psrc)^; inc(pByte(psrc)); b1 := pByte(psrc)^; result := result + CT64[(b0 shr 2) and $3f] + CT64[((b0 shl 4) and $30) or ((b1 shr 4) and $0f)] + CT64[(b1 shl 2) and $3c] + '='; end else if r=1 then begin b0 := pByte(psrc)^; result := result + CT64[(b0 shr 2) and $3f] + CT64[(b0 shl 4) and $30] + '=='; end; end; end; var s: ansistring; const xx: array[0..5] of byte = ($02, $01, $AA, $B6, $00, $00) ; begin s := Base64Str(@xx, sizeof(xx)); writeln(s); end. |
AW: Hex to Base64
Liste der Anhänge anzeigen (Anzahl: 1)
Diese Unit habe ich mal unter Delphi 3 genutzt. Ist sehr einfach zu handhaben (ein Beispiel ist in der Unit bei).
|
AW: Hex to Base64
Zusammenfassend kann man also sagen, das so eine HEX-Zeichenfolge eine Folge von Bytes darstellt, was im Übrigen auch so eine Base64-Zeichenfolge macht.
BTW Diese HEX-Zeichenfolge kann man auch als Base16-Zeichenfolge bezeichnen. Somit ist auch der Weg klar: HEX-Zeichenfolge => Byte-Folge => Base64-Zeichenfolge |
AW: Hex to Base64
|
AW: Hex to Base64
Also ersteinmal vielen vielen Dank für eure Antwort. Ich stecke in der "binären" Materie leider einfach noch nicht wirklich drin und bin von den ganzen Dingen derzeit überwältigt. Ich kann euch mal erklären, wie sich der HEX-Wert zusammensetzt, vielleicht gibt es dann eine bessere Lösung:
02 01 AA B6 00 00 1.Byte: 02 (immer) 2.Byte: eine Zahl von 1-250 (im Hex-Format) 3-xByte: eine Zahl von 1-X im Format little endian (das macht mir gerade auch zu schaffen) auch HEX x+1Byte: ein 0-Byte Ich habe gerade schon damit scheusslich Probleme, weil ich das mit dem little endian nicht gebacken bekomme. Derzeit ist meine Lösung einfach nur hässlich. Ich konvertiere die Zahl (1-X) in einen Hex-String und schiebe dann jeweils in Zweierpäckchen die Bytes in die andere Reihenfolge. Auf diesem Weg schaffe ich es zwar, den HEX-Code als String darzustellen, aber am Rest scheitere ich kläglich. Am Besten wäre es natürlich, wenn ich einfach direkt alles in ein Byte Array gepackt bekomme, aber dafür reicht mein Wissen leider nicht aus. Es wäre genial, wenn ihr hierbei nochmal helfen könntet :) Vielen vielen Dank schonmal für die Zahlreichen Antworten! |
AW: Hex to Base64
Zitat:
Das könnte hilfreich sein. Gruß K-H P.S. Hex ist übriges das gleiche wie Base16 :zwinker: |
AW: Hex to Base64
Achsoooooo :D jetzt weiß ich endlich was base 64 ist :DDD danke :P Ich schau mir deinen Post nochmal genauer an
EDIT: Ja hier ist auch schon das Problem: Der Wert für das 2. Byte liegt als String vor (dezimal, 1-250). Der Wert für die Bytes danach liegt ebenfalls als String vor (aber nicht little endian sondern eben normal). Ich weiß weder, wie ich den Wert für Byte 2 als Byte konvertiere, noch wie ich einen Integer beliebiger länge (Byte 3-x) in ein little endian byte array konvertiere. Vor allem deswegen, weil die größe eines Integers - soweit ich weiß - unter 32 und 64bit unterschiedlich ist.. |
AW: Hex to Base64
Sind da wirklich Leerzeichen zwischen den Hex-Werten?
|
AW: Hex to Base64
Zitat:
Delphi-Quellcode:
Darunter können wir uns dann konkret etwas vorstellen
function Foo( Arg1 : Byte; Arg2 : string; Arg3 : Int64 ) : string;
begin // da weiss ich nicht wie end; procedure Test; begin Assert( // Eingangswerte Foo(42, '42', 42) // erwartetes Ergebnis = 'Magic' ); end; |
AW: Hex to Base64
Ich weiß nicht genau was du meinst, aber ich versuche gerade aus Werten einer Datenbank einen Base64 kodierten String zu erstellen, mit dem ein anderes Programm arbeiten kann. Dazu habe ich den genannten Aufbau:
1.Byte: Header (immer 02) 2.Byte: Anzahl (liegt als String vor: Beispiele: 1;15;123;250;... -> der Wert schwankt zwischen 1 und 250) 3-xByte: ID (liegt als String vor: Beispiele: 1;2345;65234;... -> der Wert ist immer positiv und ungleich 0 ansonsten theoretisch beliebige größe, derzeit aber nich größer als 3Bytes) x+1Byte: 0Byte Mein Ansatz zum Erstellen des Byte Arrays:
Delphi-Quellcode:
Ich hoffe das Problem ist jetzt klar. Wenn ich das Byte Array erstmal richtig aufgebaut habe, versuche ich mal #2 :)
procedure TForm1.Button1Click(Sender: TObject);
var BArray: TByteDynArray; s2: string; t: Byte; begin SetLength(BArray, ?); //Ich weiß vorher noch nicht wie groß es wird, weil die ID ja beliebig groß ist BArray[0] := $02; t := StrToInt(ed_anzahl.Text); BArray[1] := t; //hier müsste ich dann die ID als little endian, also verkehrt herum hinzufügen BArray[?] := $00; end; |
AW: Hex to Base64
Zitat:
b) Du hast eine Struktur
In Deinem Beispiel wäre das ein 24Bit Integer. D.H. Du benötigst mehrere Byte-Arrays mit unterschiedlichen Längen oder ein Byte-Array [0..10] und eine Längenangabe wieviele Bytes übersetzt werden sollen. Und zu Little Endian: dez:511 = x01FF [little Endian] = xFF01 [BigEndian] Gruß K-H Nachtrag: was spricht dagegen 17 als x11 oder x0011 oder x000011 oder x00000011 ... zu betrachten? |
AW: Hex to Base64
Ok, ich versuche jetzt mal das
Zitat:
Ist das jetzt soweit korrekt? PS: Bitte zeige uns auch noch den Wert der ID, die dann zu deinem Eingangs-Beispiel 02 01 AA B6 00 00 führt. |
AW: Hex to Base64
Okay, ich habe mir nochmal genau angeschaut, wie der Base64 Code vom dem besagten Programm selbst generiert wird:
1 Byte: Header 1 Byte: Anzahl 4 Byte: ID 1 Byte: 0-Byte Das bedeutet, das ByteArray hätte immer die größe 7Byte! Header und Anzahl bekomme ich nun hin, das 0-Byte ist natürlich auch kein Problem. Das Problem ist derzeit nur noch die ID Ich würde dafür gerne eine saubere Lösung haben. In der Theorie weiß ich, wie man aus einem BigEndian ein LittleEndian mache, nämlich indem ich einfach die Indizes der Bytes umgekehrt anordne: BigEndian: |---0---| |---1---| |---2---| 1001 0010 1100 1010 1111 0000 Der selbe Wert als LittleEndian wäre dann ja: 1111 0000 1100 1010 1001 0010 |---0---| |---1---| |---2---| Ich müsste nun den String (decimal, zB 23;453;69121) in irgendeinen 4Byte Integer-Container eintragen und dann die Bytes von hinten nach vorne in das Array eintragen und das bekomme ich nicht hin. Also das wäre nochmal sehr lieb :) |
AW: Hex to Base64
Zitat:
Bislang waren es immer ausdrücklich 3 Bytes ... woher kommt jetzt diese wundersame Byte-Vermehrung? Und welchen Wert hat ID um auf die Byte-Folge in dem ersten Beitrag zu kommen? Obwohl, diese Byte-Folge im ersten Beitrag ist ja nun auch wieder falsch, weil nur 6 Bytes ... :roll: |
AW: Hex to Base64
Naja es ist so. Es gibt eine Wiki, wo der Aufbau dieses Konstrukts erklärt wird. Dort wird die ID nicht auf 4 Bytes festgelegt sondern ist Variabel. Das Programm selbst erzeugt die eigenen Codes konstant mit 4 Bytes, was ich vorher nicht bemerkt habe. Das heißt im Endeffekt: Das Programm erkennt alles, auch wenn die ID 2,3,5 oder 6 Bytes groß ist. Mit 4 Bytes bin ich allerdings auf der Sicheren Seite. 3 Bytes wären allerdings auch vollkommen ausreichend. Mich würden beide Varianten interessieren.. mir fehlt wie gesagt einfach der Ansatz
im ersten Beitrag war der HEX Code 02 01 AA B6 00 00 Darauf folgt: B6 AA (bzw 00 B6 AA oder bei 4 bytes 00 00 B6 AA) ist die ID in BigEndian also "46762" in Dezimal Ich brauche im Prinzip ja nur eine Möglichkeit, die 3 oder 4 Bytes (wie auch immer ist eigentlich egal) aus dem String, der in dem Fall "46762" ist herauszubekommen und das auch noch falsch herum.. |
AW: Hex to Base64
Also suchst du sowas hier
Delphi-Quellcode:
Die Ausgabe ist dann
program dp_185013;
{$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.SysUtils; procedure OutputBuffer( ABuffer: TBytes ); var I: Integer; begin for I := low( ABuffer ) to high( ABuffer ) do begin write( IntToHex( ABuffer[ I ], 2 ), ' ' ); if ( I + 1 - low( ABuffer ) ) mod 16 = 0 then Writeln; end; Writeln; end; procedure Test; var LStream: TMemoryStream; LBuffer: TBytes; begin LStream := TMemoryStream.Create; try // Daten in den Stream LStream.WriteData( $02 ); LStream.WriteData( Byte( StrToInt( '1' ) ) ); LStream.WriteData( Int32( StrToInt( '46762' ) ) ); LStream.WriteData( $00 ); // Stream-Inhalt nach TBytes kopieren SetLength( LBuffer, LStream.Size ); LStream.Position := 0; LStream.Read( LBuffer, Length( LBuffer ) ); // Ausgabe der TBytes zur Kontrolle OutputBuffer( LBuffer ); finally LStream.Free; end; end; begin try Test; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; ReadLn; end.
Code:
02 01 AA B6 00 00 00
|
AW: Hex to Base64
In diesem Zusammenhang solltest du dir auch mal diesen Beitrag durchlesen
![]() und die Lösung von mir anschauen, wie dort die Daten hin- und hergeschoben werden. ![]() |
AW: Hex to Base64
Hey,
das funktioniert perfekt.. aber kannst du mich bitte kurz aufklären, wieso die ID automatisch in LittleEndian ausgegeben wird? Macht das Int32()? |
AW: Hex to Base64
Zitat:
![]() Und nein, Int32 sorgt nur für einen 4-Byte-Integer Wert (32bit => 4 Byte) |
AW: Hex to Base64
Achso, aber unter Windows ist eh alles Little Endian.. danke :D
Ich habe jetzt eigentlich alles, was ich wollte, nur eine Sache klappt noch nicht. Ich wollte den in #2 geposteten Weg benutzen, stelle nun aber fest, dass ich dafür ein TIdBytes und nicht TBytes brauche. Außerdem kann ich kein Array vom Type TIdBytes erstellen, obwohl ich IdCoder unter uses eingebunden habe. "[dcc32 Fehler] Project1.dpr(29): E2003 Undeklarierter Bezeichner: 'TIdBytes'" Außerdem scheinen die beiden Typen auch, obwohl sie den gleichen Aufbau haben nicht kompatibel zueinander zu sein. Könnt ihr mir noch sagen, wie ich dann jetzt and meinen Base64 String aus dem TBytes Array komme? :) PS: Sir Rufo, ich habe dir in Skype mal ne Anfrage geschickt, eventuell kannst du mir da kurz helfen, da kommen wir schneller zu einer Lösung |
AW: Hex to Base64
gleicher Auffbau <> identischer Aufbau
Und ich versteh nicht, warum du TIdBytes nicht finden kannst.
|
AW: Hex to Base64
Also
Delphi-Quellcode:
befindet sich in der unit
TIdBytes
Delphi-Quellcode:
.
IdGlobal
Um von
Delphi-Quellcode:
nach
TBytes
Delphi-Quellcode:
zu kommen, kann man
TIdBytes
Es wäre auch nett, wenn du deine Delphi Version angeben könntest, dann wäre es auch einfacher dir die richtigen Units zu nennen, bzw. in den neueren Versionen sind viele Sachen schon von Haus aus enthalten. Die Delphi-Version kannst das hier im Thread machen, oder wesentlich geschickter in deinem Profil vermerken. |
AW: Hex to Base64
Und hier nochmal das Beispiel erweitert mit dem Base64 Encoding und mit einem eigenen Datentyp
Delphi-Quellcode:
program dp_185013;
{$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.NetEncoding, System.SysUtils; type TMyData = packed record Header: Byte; Amount: Byte; Data: Int32; Tail: Byte; end; procedure OutputBuffer( ABuffer: TBytes ); var I: Integer; begin for I := low( ABuffer ) to high( ABuffer ) do begin write( IntToHex( ABuffer[ I ], 2 ), ' ' ); if ( I + 1 - low( ABuffer ) ) mod 16 = 0 then Writeln; end; Writeln; end; procedure TestData; var LData: TMyData; LBuffer: TBytes; begin // Daten in den Record schreiben LData.Header := $02; LData.Amount := StrToInt( '1' ); LData.Data := StrToInt( '46762' ); LData.Tail := 0; // Buffer auf Mass bringen SetLength( LBuffer, SizeOf( TMyData ) ); // Record in einem Rutsch in den Buffer kopieren Move( LData, LBuffer[ 0 ], Length( LBuffer ) ); // Ausgabe als HEX OutputBuffer( LBuffer ); // Ausgabe als Base64 Writeln( TNetEncoding.Base64.EncodeBytesToString( LBuffer ) ); end; procedure Test; var LStream: TMemoryStream; LBuffer: TBytes; begin LStream := TMemoryStream.Create; try // Daten in den Stream LStream.WriteData( $02 ); LStream.WriteData( Byte( StrToInt( '1' ) ) ); LStream.WriteData( Int32( StrToInt( '46762' ) ) ); LStream.WriteData( $00 ); // Stream-Inhalt nach TBytes kopieren SetLength( LBuffer, LStream.Size ); LStream.Position := 0; LStream.Read( LBuffer, Length( LBuffer ) ); // Ausgabe der TBytes zur Kontrolle OutputBuffer( LBuffer ); Writeln( TNetEncoding.Base64.EncodeBytesToString( LBuffer ) ); finally LStream.Free; end; end; begin try Test; TestData; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; ReadLn; end. |
AW: Hex to Base64
Danke Sir Rufo und allen anderen. Es funktioniert perfekt.. Ich habe es vorher mit der Encode64 Funktion versucht und die lieferte mir einfach schlicht falsche Ergebnisse. Vielen Lieben Dank an alle!
|
AW: Hex to Base64
Vielleicht noch soviel, weil es nicht erwähnt wurde - allgemein (beim PC) besteht ein Byte aus 8 Bits. Früher nutzte man für Text-Nachrichten aber nur 7 Bits. Soweit ich also immer noch richtig informiert bin, wurden (oder werden immer noch) z. B. bei Emails nur 7 Bits genutzt. Das 8. Bit bleibt ungenutzt. Wie gesagt, ich weiß nicht ob das immer noch so ist, sollte es aber.
Damit ergibt sich aber die Frage wie man Dateien mit Email verschickt die 8 Bits nutzen (also de facto fast alles), Man könnte also alles auf 7 Bit runter rechnen. Das Problem dabei ist aber, dass das 7 Bit Textsystem auch Steuerzeichen nutzt. Man kann also nicht alle 127 Ascii-Zeichen (7 Bits) nutzen. Also zieht man die ersten 32 Zeichen (inkl. Null) ab. Das Leerzeichen eignet sich auch nicht, also 33. Bleiben ca. 94 Zeichen. Also 7 Bits kann man klicken. 7 Bits minus 1 Bit machen 6 Bit. Die Sonderzeichen könnte man nutzen, das ganze würde eher so 6 1/2 Bits bringen. Geht nicht. Also ganze 6 Bits, das macht 64 Zeichen. Also nimmt man die Zeichen A-Z, a-z, 0-9, = und noch ein Zeichen. Base64 ist also 8 Bit auf 6 Bit runter gerechnet. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:28 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 by Thomas Breitkreuz