String to Hex, Hex to String ohne "böse" Funktionen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    String to Hex, Hex to String ohne "böse" Funktionen

    Hi,

    ich möchte einen String in seine hexadezimale Darstellung umwandlen und dann wieder zurückübersetzen.

    MIr ist klar, dass diese Funktionen "kulturabhängig" sein müssen, da ja die Darstellung des Strings vom Encoding abhängt.

    So hab ich das hinbekommen:

    VB.NET-Quellcode

    1. Public Function S2X(ByRef s As String) As String
    2. Dim Data = s
    3. Dim sVal As String
    4. Dim sHex As String = ""
    5. While Data.Length > 0
    6. sVal = Microsoft.VisualBasic.Conversion.Hex(Microsoft.VisualBasic.Strings.Asc(Data.Substring(0, 1).ToString()))
    7. sHex = sHex & sVal.PadLeft(2, "0"c)
    8. Data = Data.Substring(1, Data.Length - 1)
    9. End While
    10. Return sHex
    11. End Function
    12. Function X2S(ByRef s As String) As String
    13. Dim sb As New System.Text.StringBuilder(s.Length \ 2)
    14. For i As Integer = 0 To s.Length - 2 Step 2
    15. sb.Append(Chr(Convert.ToByte(s.Substring(i, 2), 16)))
    16. Next
    17. Return sb.ToString
    18. End Function


    Ich habe das für alle möglichen Hex Kombinationen erfolgreich getestet.

    Trotzdem habe ich meine Zweifel an der Quallität der Funktionen.

    1. Die Routinen verwenden "alten" VB Code aus dem "Visual Basic" Namespace ...

    2. Jedes Zeichen des Eingabestrings wird in EIN Hex 2er-Tupel übersetzt. Das kann nicht allgemeingültig sein, da ja ein Zeichen in einem String durchaus aus zwei oder mehr Bytes bestehen kann.

    Wie macht man denn sowas richtig ?

    LG
    Peter
    @Peter329 Zur Darstellung einers ganzzahligen Wertes nimmst Du einfach:

    VB.NET-Quellcode

    1. Dim value = 123
    2. MessageBox.Show(value.ToString("X") & EnvironMent.NewLine & value.ToString("X2") & EnvironMent.NewLine & value.ToString("X4") & EnvironMent.NewLine & value.ToString("X8"))
    Probiere ebenfalls mit großem und kleinem "X", "x".
    Die andere Richtung geht so:

    VB.NET-Quellcode

    1. Dim txt = "abc"
    2. Dim value = Convert.ToInt32(txt, 16)
    wobei 16 die Zahlenbasis (hier: Hexadezimal) ist.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke ... das klingt sehr gut aus ! :)

    Ich hab das jetzt so umgesetzt:

    VB.NET-Quellcode

    1. 'Convert array to hex string
    2. Dim myHexString As String = ""
    3. For i As Integer = 0 To mySourceArray.Count - 1
    4. myHexString &= mySourceArray(i).ToString("x2").ToUpper
    5. Next
    6. 'Convert hex string to array
    7. Dim myTargetArray(CInt(myHexString.Length / 2 - 1)) As Byte
    8. For i As Integer = 0 To myTargetArray.Count - 1
    9. myTargetArray(i) = CByte(Convert.ToInt32(strHex.Substring(i * 2, 2), 16))
    10. Next


    Ist das mit den Schleifen so in Ordnung oder kann man die vermeiden. Ansonsten werde ich den Thread als erledigt markieren.

    Alles in allem läuft das so hervorragend. Ganz herzlichen Dank für deinen Rat !
    @Peter329 Da hast Du wohl nicht alles ausprobiert, was ich Dir geschrieben habe. ;)

    RodFromGermany schrieb:

    Probiere ebenfalls mit großem und kleinem "X", "x".

    Was soll den hinterher in Deinem Target-Array stehen (eine verbale Beschreibung bitte)?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ok, also mit dem großen "X" kann ich den Aufruf der Funktion .ToUpper vermeiden. Ich nehme an, dass es das ist, was du gemeint hast.

    Die beiden Funktionen werden gebraucht, um einen beliebigen Byte Array in einen String unzuwandeln ... und später aus diesem String genau den gleichen Byte Array zu erzeugen. (Insofern ist mein Thread Titel nicht ganz korrekt).

    Die Sache funktioniert ... und so wie ich das sehe, kann man die o.a. Routinen nicht weiter vereinfach. Aber sie sind ja auch so schon schnuckelig genug ! :)

    Danke nochmal und LG
    Peter

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Peter329“ ()

    Hi
    ggf. kämst du auch mit Base64 gut zurecht.
    Wenn es für jedes Encoding funktionieren soll, wäre folgender Ansatz evtl. genau das, was du brauchst. Der wäre auch effizienter:

    VB.NET-Quellcode

    1. Shared Function GetHexFromData(data As Byte()) As String
    2. If data Is Nothing Then Throw New ArgumentNullException(NameOf(data))
    3. 'aus diesen Buchstaben besteht der String
    4. Static chars As Char() = {"0"c, "1"c, "2"c, "3"c, "4"c, "5"c, "6"c, "7"c, "8"c, "9"c, "a"c, "b"c, "c"c, "d"c, "e"c, "f"c}
    5. 'in diesen Puffer werden die Zeichen eingelesen. Die Größe des Puffers ergibt sich aus der Länge der Eingabe: Jedes Eingabezeichen wird in zwei Ausgabezeichen konvertiert
    6. Dim sb As New System.Text.StringBuilder(data.Length * 2)
    7. For Each bt As Byte In data
    8. 'für big endian vertauschen
    9. sb.Append(chars(bt >> 4))
    10. sb.Append(chars(bt And &HF))
    11. Next
    12. Return sb.ToString()
    13. End Function
    14. Shared Function GetDataFromHex(hexString As String) As Byte()
    15. If hexString Is Nothing Then Throw New ArgumentNullException(NameOf(hexString))
    16. 'Wenn der String ungerade Länge hat, kann er nicht interpretiert werden, da immer 2 Buchstaben 1 Byte darstellen
    17. If (hexString.Length And 1) <> 0 Then Throw New ArgumentException("Input length must be a multiple of 2 as each byte must consist of two hexadecimal digits.", NameOf(hexString))
    18. Dim data(hexString.Length \ 2 - 1) As Byte
    19. For i As Integer = 0 To data.Length - 1
    20. 'für big endian (2 * i) mit (2 * i + 1) vertauschen
    21. data(i) = (GetHexCharacterValue(hexString(2 * i)) << 4) Or GetHexCharacterValue(hexString(2 * i + 1))
    22. Next
    23. Return data
    24. End Function
    25. Private Shared Function GetHexCharacterValue(character As Char) As Byte
    26. If character >= "0"c AndAlso character <= "9"c Then
    27. Return CByte(Asc(character) - Asc("0"c))
    28. ElseIf character >= "A"c AndAlso character <= "F"c Then
    29. Return CByte(10 + Asc(character) - Asc("A"c))
    30. ElseIf character >= "a"c AndAlso character <= "f"c Then
    31. Return CByte(10 + Asc(character) - Asc("a"c))
    32. Else
    33. Throw New ArgumentException("Character does not represent a hexadecimal digit.")
    34. End If
    35. End Function


    Beachte übrigens insbesondere die ganzzahlige Divison durch \ statt durch /. \ liefert einen Integer zurück, / einen Double.

    Edit:
    bzgl. Base64:
    Convert.FromBase64String und Convert.ToBase64String sind die jeweiligen Methoden (es gibt sie in Convert auch für Char-Arrays). Wenn es dir nur um die String-Repräsentation geht, ist das wohl die Wahl, die ich treffen würde.

    Viele Grüße
    ~blaze~
    @~blaze~ Jou.
    @Peter329 Zu Base64 hab ich folgendes Snippet:

    VB.NET-Quellcode

    1. Dim bb() As Byte = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
    2. Dim bb64 = Convert.ToBase64String(bb)
    3. Dim bb2 = BitConverter.ToString(bb)
    4. Dim b2() = Convert.FromBase64String(bb64)
    Falls es sich dabei um ein Image handelt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Form mit 2 Button, RichTextBox und PictureBox
    2. Imports System.IO
    3. Imports System.Drawing.Imaging
    4. Public Class Form1
    5. Dim base64 As String
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. Dim by As Byte()
    8. Dim bmp = New Bitmap("C:\Temp\Base.jpg") ' ein Bild halt
    9. Using ms = New MemoryStream
    10. bmp.Save(ms, ImageFormat.Png)
    11. by = ms.ToArray()
    12. End Using
    13. ' Länge aufgerundet bestimmen:
    14. ' https://de.wikipedia.org/wiki/Base64
    15. Dim len = CInt(by.Length * 1.4)
    16. ' Char-Array für den Base64-String
    17. Dim charArray As Char() = New Char(len) {}
    18. Dim len2 = Convert.ToBase64CharArray(by, 0, by.Length, charArray, 0, Base64FormattingOptions.InsertLineBreaks)
    19. Me.base64 = New String(charArray, 0, len2)
    20. Me.RichTextBox1.Text = base64
    21. End Sub
    22. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    23. ' Deserialisierung:
    24. ' Aus dem Base64-String ein Byte-Array generieren
    25. Dim array As Byte() = Convert.FromBase64CharArray(base64.ToCharArray(), 0, base64.Length)
    26. ' und als Bitmap instanziieren
    27. Using ms As New MemoryStream(array)
    28. Me.PictureBox1.Image = New Bitmap(ms)
    29. End Using
    30. End Sub
    31. End Class

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!