Convert String To ByteArray and ByteArray To String

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

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von exc-jdbi.

    Convert String To ByteArray and ByteArray To String

    Hi,

    das Thema String, Char und Byte ist mir nach wie vor noch nicht so richtig transparent.

    Ein "Char" enthält ein Zeichen. Ein Char ist wohl zwischen ein und zwei Bytes lang abhängig vom Encoding (z.B. ASCII, Unicode UTF-8 bzw. UTF-16, etc.)

    Ein "String" ist ein Array von "Char" (wird aber nicht als array präsentiert und hat somit keinen Index). Insbesondere ist der Inhalt des Strings vom Encoding abhängig.

    Ein "Byte" hat acht Bits, also immer dieselbe Länge. Es enthält eine Bitkombination die einer Zahl zwischen 0 und 255 entspricht. Insbesondere hat ein Byte kein Encoding.

    Ich hoffe, ich hab das alles richtig verstanden.

    Nun würde ich gern einen ByteArray als CommandArgument übergeben. Dazu wird ein STRING benötigt. Und deshalb würde ich gern im rufenden Programm meinen ByteArray in einen String umwandeln ... und dann im gerufenen Programm aus dem übergebenen String wieder den Byte Array daraus machen.

    Das ist wohl nicht so einfach wie es sich anhört. So habe ich das versucht:

    VB.NET-Quellcode

    1. Public TestByteArray As Byte() = {&H41, 65, &H54, &H31, &H3F, &H20, &H46, &H55}
    2. Dim TestString As String = ""
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. For i As Integer = 0 To 7
    5. 'Array to string
    6. TestString &= Chr(TestByteArray(i))
    7. Next
    8. TextBox1.Text = TestString
    9. End Sub
    10. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    11. 'String to array
    12. For i As Integer = 0 To 7
    13. Dim myDigit As String = TestString.Substring(i, 1)
    14. TestByteArray(i) = CByte(myDigit)
    15. Next
    16. End Sub


    Die Conversion Byte nach String klappt wie erwartet.

    Die Conversion String nach Byte klappt (wie erwartet) NICHT ! Beim ersten Zeichen (dem Buchstaben "A") erhalte ich im Cbyte eine Invalid Cast Exception.

    Wie macht man das denn richtig ? Ich muss erreichen, dass die Conversion 100% reversibel ist ! Aus dem Byte Array wird ein String .... und aus dem String muss exakt der gleiche Byte Array herauskommen. Unabhängig davon, welches Encoding aktiv ist !

    LG
    Peter
    Hallo @Peter329

    Probiers mal mit Encoding aus dem Namespace System.Text.Encoding

    VB.NET-Quellcode

    1. Dim enc As System.Text.Encoding = System.Text.Encoding.Default
    2. TestByteArray = enc.GetBytes(TestString)


    Ich denke das sollte funktionieren.
    So geht's auch einfacher in die andere Richtung

    VB.NET-Quellcode

    1. Dim enc As System.Text.Encoding = System.Text.Encoding.Default
    2. TestString = enc.GetString(TestByteArray)


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Peter: jo - dassis nicht ganz undurcheinander ;)
    Also Char enthält kein Zeichen, sondern ist einfach der Datentyp für SchriftZeichen. Char ist ein primitiver Datentyp und nimmt 16 Bit (2 Byte) Speicherplatz ein. Immer.
    String ist der Datentyp für Text - ein String enthält kein oder viele Chars, und darüber hinaus viel Funktionalität, um Text zu verarbeiten.
    Obwohl String kein Char-Array ist, kann man dennoch seine Chars indiziert abrufen:

    VB.NET-Quellcode

    1. Dim c = "banana"(2) ' = "n"c
    Ja es gibt sogar eine automatische Konvertierung (aber nur in eine Richtung):

    VB.NET-Quellcode

    1. Dim s As String = {"b"c, "a"c, "n"c} ' = "ban"


    Byte ist der Datentyp für positive kleine ganze Zahlen - 8 Bit. Ausserdem ist Byte die kleinste Daten-Einheit, mit der ein Rechner umgeht. Auch nennt man es Bytes, was in Dateien auf Platte geschrieben ist - also letztendlich besteht alles aus Bytes.

    Ein Encoding ist ein Konverter, der Byte-Folgen nach String konvertiert und zurück.
    Diese Konversion kann unterschiedlich erfolgen - manche Encodings produzieren kompakteren Byte-Code als andere, manche Zeichen im String ergeben je nach Encoding andere Bytes oder Byte-Folgen.

    Peter329 schrieb:

    Unabhängig davon, welches Encoding aktiv ist !
    Tja - was bei der Konversion herauskommt hängt aber nunmal ab vom verwendeten Encoding.
    Und beachte: Ein Encoding wandelt nicht einzelne Chars zu einzelnen Bytes, sondern ein Encoding wandelt ByteFolgen zu Strings - das ist ein Unterschied.

    Ich weiß nun nicht, was du konkret vorhast, aber wenn du einzelne Chars zu einzelnen Bytes wandeln willst, verwende die Methoden der Convert - Klasse. Gut möglich, dass nicht jeder Byte-Wert in einen Char gewandelt werden kann und zurück - ich hab nicht alle ausprobiert.

    Willst du Byte-Folgen nach String konvertieren, verwende ein Encoding - und dabei ist egal welches, hauptsache in beide richtungen dasselbe.
    Hierbei ist zu beachten, dass bestimmte bescheuerte Byte-Folgen unlesbare Strings ergeben. Dennoch sind diese Strings korrekt, und die re-Konvertierung erbringt die originale bescheuerte Byte-Folge.

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

    Peter329 schrieb:

    Ein "String" ist ein Array von "Char" (wird aber nicht als array präsentiert und hat somit keinen Index). Insbesondere ist der Inhalt des Strings vom Encoding abhängig.
    Das ist so nicht ganz richtig.
    Aus einem String kannst Du per Index den jeweiligen Char auslesen:

    VB.NET-Quellcode

    1. Dim txt = "012345"
    2. MessageBox.Show(txt(2).ToString())
    Und der Inhalt des Strings ist nicht abhängig vom Encoding, sondern die Konvertierung von Bytes in einen String liefert, je nach Encoding, andere Strings.
    Das hängt damit zusammen, dass die ANSI-Zeichen 128 bis 255 je nach Kultur anders belegt sind, ein Rudiment aus der DOS-Zeit.
    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!
    Guten Morgen Peter

    So quasi als Übersicht. Das könnte eventuell Licht in all deine Fragen bringen. Ungetestet.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Text
    4. Public Module Module1
    5. Public Sub Main()
    6. 'Beispiel 1
    7. Dim b1() As Byte = {&H41, 65, &H54, &H31, &H3F, &H20, &H46, &H55}
    8. Dim s1 As String = ByteArrToString(b1)
    9. Dim b2() As Byte = StringToByteArray(s1)
    10. If CheckEquals(b1, b2) Then
    11. Stop 'Beispiel 1 OK
    12. End If
    13. 'Beispiel 2
    14. Dim s2 As String = Encoding.Default.GetString(b1) 'WICHTIG: NUR Bereich Ascii 0 - 255
    15. Dim b3() As Byte = Encoding.Default.GetBytes(s2)
    16. If CheckEquals(b1, b3) Then
    17. Stop 'Beispiel 2 OK
    18. End If
    19. End Sub
    20. Private Function ByteArrToString(ByVal b() As Byte) As String
    21. If b.Length > 0 Then
    22. Dim sTmp As String = String.Empty
    23. For i As Integer = 0 To b.Length - 1
    24. sTmp &= Chr(b(i)) 'WICHTIG: NUR Bereich Ascii 0 - 255
    25. Next
    26. Return sTmp
    27. End If
    28. Return String.Empty
    29. End Function
    30. Private Function StringToByteArray(ByVal s As String) As Byte()
    31. If s.Length > 0 Then
    32. Dim bTmp() As Byte = New Byte(s.Length - 1) {}
    33. For i As Int32 = 0 To s.Length - 1
    34. bTmp(i) = CByte(Asc(s(i))) 'WICHTIG: NUR Bereich Ascii 0 - 255
    35. Next
    36. Return bTmp
    37. End If
    38. Return Nothing
    39. End Function
    40. Private Function CheckEquals(ByVal b1() As Byte, ByVal b2() As Byte) As Boolean
    41. If b1.Length = b2.Length Then
    42. For i As Int32 = 0 To b1.Length - 1
    43. If Not (b1(i) Mod b2(i)) = 0 Then
    44. Return False
    45. End If
    46. Next
    47. Return True
    48. End If
    49. Return False
    50. End Function
    51. End Module


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hmm, hmm - Chr und Asc sind mir suspekt, weil deren Verhalten weicht von dem der Convert-Klasse ab:

    VB.NET-Quellcode

    1. Private Sub TestByteCharConversions()
    2. Dim c1s = New List(Of Char)
    3. Dim c2s = New List(Of Char)
    4. For i = 0 To 255
    5. Dim c1 = Microsoft.VisualBasic.Chr(CByte(i))
    6. Dim c2 = Convert.ToChar(CByte(i))
    7. If c1 <> c2 Then Stop ' verschiedene Ergebnisse
    8. c1s.Add(c1)
    9. c2s.Add(c2)
    10. Next
    11. For i = 0 To 255
    12. Dim n1 = Microsoft.VisualBasic.Asc(c1s(i))
    13. Dim n2 = Convert.ToByte(c2s(i))
    14. If n1 <> n2 Then Stop ' verschiedene Ergebnisse
    15. Next
    16. End Sub

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

    Hi,

    erstmal wieder vielen Dank für eure Antworten.

    Dann korrigiere ich mein "Weltbild": ein char ist IMMER zwei Bytes lang ... ein String kann doch über einen Index angesprochen werden ... und das Encoding bestimmt, wie Zeichen in einen String eingelesen bzw. aus dem String ausgelesen werden. Vor allem die Beiträge von EDR und Niko Ortner haben mir sehr geholfen.

    Demgemäß muss ich also nur darauf achten, dass der Konvertierung in beiden Richtungen mit dem gleichen Encoding erfolgen. Und somit ist das Coding von Nofear23m genau das, was ich benötige.

    Ich habe das Coding für alle möglichen Byte() Inhalte (0 - 255) getestet. Die Sache klappt hervorragen ! Ich bin begeistert ! Also, Daumen hoch, Problem gelöst ... und einen schönen Sonntag.

    LG
    Peter
    Guten Morgen

    Convert.ToByte nutzt generell die UniCode-Variante, was dem AscW entsprechen sollte.
    Genauso Convert.ToChar, das wäre ChrW.
    Wie EDR Anfangs geschrieben hat, sind beide Varianten Kulturunabhängig.

    Eigentlich ist chr und asc alter VB-Code und Kulturabhängig, wird aber immer noch viel verwendet.

    Hier




    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()