Bytes, Bytearrays und umwandlung einzelner bytes in Integer/Double

  • VB.NET
  • .NET 4.5

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von dive26.

    Bytes, Bytearrays und umwandlung einzelner bytes in Integer/Double

    Hallo liebe Leute,

    Ich habe eine Datei die ich in ein ByteArray einlese.
    Die ersten 43 bytes der Datei kann man Klartext auslesen, der Rest sind bytes.

    Dier erste Aufgabe: nur die ersen 43 Bytes in einen String umwandeln.
    Es funktioniert. Aber ist das richtig so oder gibt es da kürzere (und vor allem schnellere) Varianten?

    VB.NET-Quellcode

    1. Dim rmBytes As Byte() = System.IO.File.ReadAllBytes(rMFilename)
    2. Dim _43Bytes(43) As Byte
    3. Array.Copy(rmBytes, 0, _43Bytes, 0, 43)
    4. Dim DieErsten43BytesAlsString as String = Encoding.UTF8.GetString(_43Bytes)



    Die zweite Aufgabe die ich nicht weiß wie ich Sie angehen soll ist das Auslesen einzelner Werte.
    Jeweils 4 Bytes ergeben einen integer oder floating Wert. Ich habe unten bereits das Grundgerüst für die Funktion,
    aber leider keine Ahnung wie ich z.B. aus den Bytes 44-47 des Bytearrays den Integerwert rausbekomme.
    Da gibts auch irgendwas mit Bytes linksbündig oder rechtsbündig (ich weiß den Ausdruck nicht) - hier sollte laut Dateibeschreibung die Standardausrichtung passen.

    VB.NET-Quellcode

    1. 'Der Funktion wird ein bytearray in variabler Länge übergeben
    2. 'Die ersten 43 bytes enthalten einen String
    3. 'Dann folgen jeweils 4 Bytes die Integer oder Floating repräsentieren. Beispiel:
    4. '44-47 = 4 bytes integer
    5. '48-51 = 4 bytes Integer
    6. '52-55 = 4 bytes floating point
    7. '...
    8. ' Ich möchte nun als Beispiel die 4 bytes aus dem Index 44-47 zu einem Integer oder double wandeln (einfach alles als Double übergeben)
    9. Dim Wert As Double = GetValueFromByteArray(rmBytes, 44, 4)
    10. Public Function GetValueFromByteArray(bytearray As Byte(), start As Integer, count As Integer) As Double
    11. ' Ich habe aber keinen blassen Schimmer wie ich das anstelle.
    12. 'Es sollte eine schnelle Version sein - da viele Daten zu verarbeiten sind
    13. Return 0
    14. End Function


    Könnt Ihr mir bei den beiden Fragen einen Tipp geben oder mit ein paar Codezeilen aushelfen?
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    Zumindest zu Frage 1 kann ich m.E. was beisteuern:

    VB.NET-Quellcode

    1. Dim rmBytes = System.IO.File.ReadAllBytes(rMFilename)
    2. Dim DieErsten43BytesAlsString = Encoding.UTF8.GetString(rmBytes.Take(43).ToArray)
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Hey super. Das ist ja viel viel Kürzer als mein Gefummel mit Array.Copy.

    VB.NET-Quellcode

    1. Array.Copy(rmBytes, 0, _43Bytes, 0, 43)
    2. Dim DieErsten43BytesAlsString = Encoding.UTF8.GetString(_43Bytes)
    3. ' vs
    4. Dim DieErsten43BytesAlsString = Encoding.UTF8.GetString(rmBytes.Take(43).ToArray)


    Bei meiner Variante kann man zwar von jedem Index weg auslesen, aber das wird in diesem speziellen Fall auch nicht benötigt.
    Erstes Problem ist also schon gelöst. :thumbsup:

    Bin schon neugierig auf die Lösung meines 4-byte to Integer Problem ;-).
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com
    Für Frage 2:

    C#-Quellcode

    1. ​byte[] ausgeleseneBytes= new byte[4];
    2. using (BinaryReader reader = new BinaryReader(new FileStream(file, FileMode.Open)))
    3. {
    4. reader.BaseStream.Seek(44, SeekOrigin.Begin);
    5. reader.Read(ausgeleseneBytes, 0, 4);
    6. }


    ist ungetestet aussem kop sollte aber so klappen wenn mich nicht alles täuscht.
    Schau dir einfach mal den BinaryReader an in der MSDN oder anderen Beispiele per Google.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    dive26 schrieb:

    Bei meiner Variante kann man zwar von jedem Index weg auslesen

    Och, das geht auch ohne Probleme:

    VB.NET-Quellcode

    1. Dim DieAntwortAufAllesAbPosition666 = Encoding.UTF8.GetString(rmBytes.Skip(666).Take(42).ToArray)
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Och, das geht auch ohne Probleme:


    Ich bewundere Euch gelernten Programmierer. Ihr seid echte Wunderwuzies (=positiver Kosename ;-).
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com

    dive26 schrieb:

    Euch gelernten Programmierer
    Ich gestehe: Ich bin keiner. 4 Jahre Forenaktivität haben mich von grottenschlechtem, mehr oder weniger selbstbeigebrachten Codeverhau auf mein heutiges Niveau gebracht. Ich bin gespannt, mit welchen Gedanken ich in 5 Jahren auf meinen heutigen Code schaue …
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @xChRoNiKx


    ist ungetestet aussem kop sollte aber so klappen wenn mich nicht alles täuscht.
    Schau dir einfach mal den BinaryReader an in der MSDN oder anderen Beispiele per Google.


    Du hast damit mit einem Schlag meine 2. Frage beantwortet und jetzt ist mir auch ein Knoten aufgegangen.
    Vielen Dank :thumbsup:

    VB.NET-Quellcode

    1. 'Hier alle Daten auslesen
    2. Dim pos As Long = 0
    3. Using reader As New BinaryReader(File.Open(rMFilename, FileMode.Open))
    4. Dim rmDataLength As Long = reader.BaseStream.Length
    5. While pos < rmDataLength
    6. reader.BaseStream.Seek(44, SeekOrigin.Begin) ' Fileheader (43 Bytes) überspringen
    7. Dim value As Integer = reader.ReadInt32() 'integer auslesen (4 Bytes)
    8. 'Hier Schleifen erstellen und Daten verarbeiten
    9. pos += 4 'Positionszähler erhöhen
    10. End While
    11. End Using


    Ich gestehe: Ich bin keiner. 4 Jahre Forenaktivität haben mich von grottenschlechtem, mehr oder weniger selbstbeigebrachten Codeverhau auf mein heutiges Niveau gebracht. Ich bin gespannt, mit welchen Gedanken ich in 5 Jahren auf meinen heutigen Code schaue …


    Das geht mir genau so. Habs auch nicht gelernt und habe dennoch schon viel hinbekommen. Mein Code ist dennoch immer noch grottenschlecht. Er funktioniert, aber schön ist er nicht.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    VB.NET-Quellcode

    1. pos += 4 'Positionszähler erhöhen
    Der Stream hat eine Propeerty .Position, die kannst Du abfragen.
    In dem Moment, wo Du mehrere Werte nacheinander ausliest, musst Du diesen Test While pos < rmDataLength nach jedem gelesenen Wert abfragen.
    Andererseits kannst Du Dir die Anzahl der vorhandenen Werte berechnen und die in einer Schleife auslesen.
    Wenn der Stream Deine Struktur enthält, testest Du initial, ob die Länge ausreicht und kannst das Einlesen gleich sein lassen, wenn der Stream zu kurz 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!
    @RodFromGermany

    ja vielen Dank. Habe ich gestern noch bis 3 Uhr früh erledigt gehabt.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com
    Bytes, Bytearrays und umwandlung einzelner bytes in Integer/Double

    Dazu kannst du auch ganz leicht die Bitconverter-Klasse verwenden...
    Hier wird auch die Bytereihenfolge ("Endianness") berücksichtigt, in der Daten in einer Computerarchitektur gespeichert werden.

    VB.NET-Quellcode

    1. 'Gibt eine 32-Bit-Ganzzahl mit Vorzeichen zurück, die aus vier Bytes an einer bestimmten Position in einem Byte-Array konvertiert wurde.
    2. Dim _int = BitConverter.ToInt32(DeinByteArray, PositionImArray)
    3. 'Gibt eine Gleitkommazahl mit doppelter Genauigkeit zurück, die aus acht Bytes an einer bestimmten Position in einem Byte-Array konvertiert wurde.
    4. Dim _dbl = BitConverter.ToDouble(DeinByteArray, PositionImArray)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB1963“ ()

    Encoding.GetString (und die Umkehrung davon, also .GetBytes) hat Überladungen, bei denen man Offset und Länge angeben kann: Encoding.UTF8.GetString(rmBytes, 0, 43)

    Übrigens: Das 43Bytes-Array hat nicht 43 Plätze sondern 44. Bei VB ist das eine Altlast, dass man den höchsten Index angibt, und nicht die Länge.
    Dim _43Bytes(43 - 1) As Byte wäre richtig.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Noch eine kleine Anmerkung zu Array.Copy vs. bytes.Skip(...).Take(...).ToArray(), da du in deinem ersten Post nach Performance gefragt hast:
    Array.Copy ist schneller als die LINQ Alternative. Wenn du, wie in deinem ersten Problemfall, nur ein einziges Mal den Header auslesen musst macht es im Endeffekt keinen (relevanten) Unterschied, weshalb du problemlos die Skip/Take Funktionen nutzen kannst. Solltest du das Ganze allerdings irgendwann mal oft hintereinander machen müssen (beispielsweise in einer Schleife) solltest du definitiv Array.Copy oder andere Alternativen wie den BinaryReader benutzen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „shad“ ()

    Vielen Dank Euch allen.

    @shad
    Der Header wird pro Datei nur einmal ausgelesen, also passt das von der Performance.

    Den Rest der Datei mach ich mit dem Using reader As New BinaryReader(File.Open(rMFilename, FileMode.Open)) und hangle mich dann Schleife für Schleife durch die Binärdatei. Das geht überraschenderweise sehr schnell und das File ist in etwa 1 Sekunde ausgelesen auch schon gerendert. Nun habe ich alles geschafft und das Testprojekt für meine eigene .dll ist fertig. Ich bin nun sogar schon so weit, dass ich aus den Binärdaten (sind alles layers, strokes und segments) eine SVG Datei erstellen kann. Und als Krönung habe ich mit der Image.Drawing Klasse sogar einen Rederer geschrieben der das ganze in eine Bitmap schreibt.

    In der Anlage findet Ihr einmal einen Screenshot vom "Experimentaltool" wo links die Vorlage (Hintergrund) und rechts das geschriebene/gerenderte auf der Vorlage zu sehen ist. Und einmal ein SVG-Export und einmal ein Export des Images das ich mit dem eigenen Renderer erstellt habe.

    Ich hätte noch vor 2 Wochen nicht gedacht, dass ich das nur ansatzweise hinbekomme, da es schon beim Auslesen und interpretieren der .rm Datei gehapert hat. Es gibt keine offiziellen Unterlagen darüber, nur ein paar ältere Github-Infos für ältere Versionen.
    Bilder
    • ImageRendering.jpg

      636,29 kB, 1.404×1.872, 15 mal angesehen
    • SVG.jpg

      511,45 kB, 718×1.017, 16 mal angesehen
    • Tool.jpg

      506,03 kB, 1.059×802, 17 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): bocomponent.com | freeremarkabletools.com