erste 4 Byte aus Hexfile in INT konvertieren



  • Nick Unbekannt schrieb:

    Die Union umgeht einfach nur die Notwendigkeit des Castings. Technisch gesehen passiert bei beiden das gleiche. Die Notwendigkeit besteht nur darin, die Typsicherheit gewährleisten zu können.
    Alternativ kannst du aber auch mit IO-Streams arbeiten, dann werden deine Daten als Texte gespeichert. Damit umgehst du zwar das Problem der Endianness gekonnt, handelst dir aber andere Probleme ein.

    welche Probleme handle ich mir damit ein?
    Hast du dafür ein Beispiel?



  • OK, man kann die Notwendigkeit von ntohl( ) auch umgehen, indem man selbst feststellt, welches Endian die eigene Architektur benutzt und dann nach Bedarf die Bytes tauscht:

    Z.B. das hier (aus einem Forum:)

    bool is_big_endian( void )
    {
        int i = 1;
        unsigned char *pc = (unsigned char*)&i;
        return (pc[0] == 0); /* most significant byte is stored first for big_endian */
    }
    

    Andere Frage: Bist Du an dieses binäre Dateiformat gebunden, d.h. ist das eine Vorgabe oder kannst Du das frei bestimmen? In letzten Fall könnte man die Zahlen auch im Klartext einfach in die Datei schreiben (das ist das mit den Streams) und wieder auslesen.



  • Ups, ja natürlich falscher Bitoperator.. War schon spät 😉

    @daffi: Probier mal meinen Code aus, dann brauchst du keine union, keinen ntohl und musst dir nicht um endianness Sorgen zu machen (da wie ich im ersten Post ja lese die Struktur der Datei gegeben ist) sondern musst nur die ersten 4 Bytes der Datei einlesen.

    unsigned char bytes[4];
    
    // bytes einlesen aus datei
    
    unsigned long result = (((unsigned long)bytes[0]) << 24)
      | (((unsigned long)bytes[1]) << 16)
      | (((unsigned long)bytes[2]) << 8)
      | ((unsigned long)bytes[3]);
    


  • minastaros schrieb:

    OK, man kann die Notwendigkeit von ntohl( ) auch umgehen, indem man selbst feststellt, welches Endian die eigene Architektur benutzt und dann nach Bedarf die Bytes tauscht:

    Z.B. das hier (aus einem Forum:)

    bool is_big_endian( void )
    {
        int i = 1;
        unsigned char *pc = (unsigned char*)&i;
        return (pc[0] == 0); /* most significant byte is stored first for big_endian */
    }
    

    Andere Frage: Bist Du an dieses binäre Dateiformat gebunden, d.h. ist das eine Vorgabe oder kannst Du das frei bestimmen? In letzten Fall könnte man die Zahlen auch im Klartext einfach in die Datei schreiben (das ist das mit den Streams) und wieder auslesen.

    Ja ich bin an das Format gebunden ...

    Ok also gibt die Funktion true zurück wenn es big Endian ist und sonst false,richtig?



  • daffi schrieb:

    Ja ich bin an das Format gebunden ...

    Ok also gibt die Funktion true zurück wenn es big Endian ist und sonst false,richtig?

    FFS, wenn du nicht mal auf meine Posts inkl. korrekter Lösung antwortest, dann wunder dich net wenn dir irgendwann keiner mehr hilft 😡



  • NewSoftzzz schrieb:

    daffi schrieb:

    Ja ich bin an das Format gebunden ...

    Ok also gibt die Funktion true zurück wenn es big Endian ist und sonst false,richtig?

    FFS, wenn du nicht mal auf meine Posts inkl. korrekter Lösung antwortest, dann wunder dich net wenn dir irgendwann keiner mehr hilft 😡

    So ich bins mal wieder 😉
    Sorry ich hatte deinen Beitrag schlicht und einfach überlesen,da er auf der neuen Seite erschien.

    Ich habe deins ausprobiert und muss sagen es funktioniert sehr gut!

    Kannst du das kurz erklären?
    Danke für die Arbeit!



  • daffi schrieb:

    Kannst du das kurz erklären?

    Ein unsigned long besteht aus mind. 32 bit, das sind 4 bytes. Da du die bytes einzeln einliest, müssen die halt wieder auf ihre richtige Position verschoben werden und dann verbunden werden. Das erste Byte wird dann halt 24 bits nach links verschoben und so weiter, damit jedes Byte an der richtigen Stelle steht. Dann werden diese Bits alle noch mit | verbunden, so dass die komplette Zahl entsteht. Wichtig ist halt vorher nur auf unsigned long zu casten, damit man auch mind. 32 bits Platz hat.

    PS: Statt unsigned long kannst du auch uint32_t nehmen, wenn du

    #include <cstdint>
    

    benutzt, das sind genauer definierte Typen die gerade für so Bitoperationen sinnvoll sind.

    mfg, René~



  • Also wenn das was vorgeschlagen hat funktioniert, dann funktioniert auch ein read mit einer int-Variable.
    Ich hab so den Eindruck du hast noch nicht den richtigen Durchblick, wie das funktioniert mit den Speichern von Daten in Variablen und was es mit der Endianness auf sich hat?



  • Nick Unbekannt schrieb:

    Also wenn das was vorgeschlagen hat funktioniert, dann funktioniert auch ein read mit einer int-Variable.
    Ich hab so den Eindruck du hast noch nicht den richtigen Durchblick, wie das funktioniert mit den Speichern von Daten in Variablen und was es mit der Endianness auf sich hat?

    probiere es aus!
    Es geht schon wenn ich es caste nur dann kommt wieder datenmüll raus!



  • Nick Unbekannt schrieb:

    Also wenn das was vorgeschlagen hat funktioniert, dann funktioniert auch ein read mit einer int-Variable.

    Ein read mit einer int Variable ist von der Endianness abhängig. Kann, muss aber nicht funktionieren. Meine Lösung ist portabel, da die Quelldatei ein festgelegtes Format hat.

    mfg, René~



  • daffi schrieb:

    probiere es aus!

    Ich brauche da nichts ausprobieren. Ich mache das schon seit Jahren und weiß warum es funktioniert und das es funktioniert.

    daffi schrieb:

    Es geht schon wenn ich es caste nur dann kommt wieder datenmüll raus!

    Ein Cast produziert keinen Datenmüll. Ein Cast macht, mal abgesehen von speziellen C++-Casting-Operatoren für die Polymorphie, genau gar nichts. Du teilst damit nur dem Compiler mit, der Typ ändert sich hier.

    Wenn dein Programm also trotzdem nicht funktioniert, dann verschweigst du uns irgendein Detail.



  • NewSoftzzz schrieb:

    Ein read mit einer int Variable ist von der Endianness abhängig. Kann, muss aber nicht funktionieren. Meine Lösung ist portabel, da die Quelldatei ein festgelegtes Format hat.

    Eine Datei muss immer ein festgelegtes Format haben, weil sie weder was von int, noch was von Endianness weiß. Eine Datei ist nichts weiter, als eine Anreihung von Bytes. Der Programmierer muss also wissen, wie die Datei aufgebaut ist und kann mit dieser Kenntnis sich seine Daten zurecht suchen. Ob ich die Daten dabei in Big-Endian oder Little-Endian speichere und oder vorher noch 42 Bytes Offset schreibe ist dabei unwichtig, ich muss es nur wissen.



  • Nick Unbekannt schrieb:

    Eine Datei muss immer ein festgelegtes Format haben, weil sie weder was von int, noch was von Endianness weiß.

    Ich bin jetzt mal genauso hochnäsig wie du in deinen 2 vorhergehenden Posts: OMG, du hast ja mal gar keine Ahnung!!!!111one

    http://en.wikipedia.org/wiki/Byte_order_mark

    mfg, René~



  • NewSoftzzz schrieb:

    Ich bin jetzt mal genauso hochnäsig wie du in deinen 2 vorhergehenden Posts:

    Wenn man 6 Seiten lang versucht etwas zu vermitteln und das einfach ignoriert wird, kann man schon mal etwas genervt sein.
    Auch gebe ich zu bedenken dass du wegen nicht mal einer Seite gleich so ein rotes Aggressions-Smilie gepostest hast.

    NewSoftzzz schrieb:

    OMG, du hast ja mal gar keine Ahnung!!!!111one

    http://en.wikipedia.org/wiki/Byte_order_mark

    Du hast den Artikel aber schon gelesen. 😃
    Es geht dabei um Texte und die BOM ist eine Kennzeichnung die vorhanden sein kann, aber nicht muss. Sprich du musst auch hier das Dateiformat kennen, um die Informationen richtig interpretieren zu können.
    Es hält dich aber keiner davon ab den Endianness-Test, der hier gepostet wurde, mit in deine Datei aufzunehmen.



  • @NewSoftzzz: Dein Code macht es geschickt, die Umwandlung von big-endian auf "myEndian" passiert implizit beim Speichern der Int-Variable... Nicht schlecht.
    Meine Aussage hinsichtlich dem Cast war falsch, habe sie entfernt. Ich hatte mal bei so einer Geschichte Problem mit dem Casten, aber der zugrundeliegende Datentyp war wohl anders. Seitdem maskiere ich zur Sicherheit lieber aus. Wieder was gelernt.

    @daffi: Nur der Vollständigkeit halber: ja, is_big_endian( ) gibt true zurück, wenn da System big endian ist. Sorry für die fehlende Info.

    Ok, vielleicht kurz zusammengefasst:

    Die Reihenfolge der Bytes in der Datei kann so oder so herum sein, das ist sozusagen das Encoding, und das kann eben big oder little endian sein. Das muss man vorher vereinbaren, damit Lesen und Schreiben funktionieren.

    Beim Lesen in das char[ ]-Array ist die Reihenfolge bekannt, daher kann man die int -Zahl kontrolliert zusammensetzen. Ob der int dann als big oder little-endian im Speicher liegt, spielt dann keine Rolle mehr.

    Liest man dagegen 4 Bytes direkt in den Speicherplatz eines int ein, muss man die Endianess des int ggf. korrigieren.


Anmelden zum Antworten