erste 4 Byte aus Hexfile in INT konvertieren



  • Vorherige Seite:

    [b]int[/b] [b]buffer[/b][4]={0};
    

    Diese Seite:

    quelle.read([b]buffer[/b], 4);
    

    Meine Frage:
    Du liest jetzt doch in den Buffer ein? Also das int-Array?

    Deine Antwort:
    1. Ist es ein Char Araay



  • Mh da hab ich bissl geschlampt.
    Das Array ist tot und hat keine bedeutung für diesen Code.
    Habs vergessen heraus zu nehmen.
    Habe aber nie über ein INT Array eingelesen.
    Dort ging das einlesen über das byte[4] Array.



  • Die Bitverschiebungsidee is ja in Ordnung wenn du VORHER auf unsigned long castest, da du sonst durch die Bitverschiebung einen Overflow auslöst.. Und dann musste natürlich noch richtig verschieben.

    unsigned long result = (((unsigned long)byte[0]) << 24) | (((unsigned long)byte[1]) << 16) | (((unsigned long)byte[2]) << 😎 | ((unsigned long)byte[3]);

    Das sollte eigentlich den Trick tun wenn du die 4 bytes richtig eingelesen hast. Allerdings funktioniert das jetzt natürlich nur für deine Quelldatei in der besagten endianness. Wenn du allerdings Kontrolle über die Quelldatei hast bzw. wie die Datei beschrieben wird kannst du den Code auch so lassen. Endianness ist ja nur dann ein Problem wenn man nicht out- und input selber auf einen Standard festlegen kann.

    mfg, René~

    EDIT: Falscher Bitoperator fixed



  • edit: Aussage über cast war falsch. Lieber gelöscht. NewSoftzzzs code ist korrekt.

    Es wurde schon mehrmals die Funktion ntohl( ) empfohlen, die diese Umwandlung erledigt, aber vorher prüft, ob sie auf dem laufenden System überhaupt notwendig ist. vielleicht wäre es jetzt an der Zeit, die entsprechende man-Page man anzusehen (oder Dr. Google zu fragen).



  • #include <iostream>
    #include <fstream>
    #include <stdio.h>
    #include<winsock2.h> //ntohl()
    
    using namespace std;
    
    int INT_little_endian_TO_big_endian(int i)
    {
        return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
    }
    
    int main()
    {
        ifstream quelle;
        quelle.open("C:\\Users\\Daffi\\Desktop\\Bearbeiten2", ios::in | ios::binary );
        if (!quelle)                              // Fehler beim Öffnen?
            cerr << "Eingabe-Datei kann nicht geöffnet werden\n";
    
            typedef union {
                int wert;
                char bytes[4];
            } LeseHelfer;
    
            LeseHelfer meinwert;
            quelle.read(meinwert.bytes, 4);
            meinwert.wert=ntohl(meinwert.wert);
            //meinwert.wert=INT_little_endian_TO_big_endian(meinwert.wert);
            cout <<meinwert.wert;
    
        quelle.close();
        getchar();
        return 0;
    }
    

    Was mache ich falsch?
    Er sagt mir: undefined reference to `ntohl@4'

    Ich kriegs es einfach nicht hin...



  • Du hast den verlinkten Artikel zu der Funktion nicht gelesen?
    Aber um das abzukürzen, du musst unter Windows die Winsock-Library linken, weil dort die Netzwerkfunktionen sind.
    Schreibe einfach unter den includes:

    #pragma comment(lib, "Ws2_32")
    

    Damit linkt Visual Studio die benötigten Funktionen. Beim gcc musst du als Linker-Option -lWs2_32 wahrscheinlich angeben. Kommt letztendlich darauf an, welche Laufzeitbibliothek genutzt wird.



  • Gut Danke, leider kann ichs grad nicht testen.

    Was mich noch interessiert ist wie das ganze ohne den union gehen würde.

    Hat dazu jemand eine Idee?



  • 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.



  • 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.


Anmelden zum Antworten