Binärdatei einlesen und einen Teil davon als Hex-Zahlen in eine andere Datei schreiben



  • Hallo,

    ich habe hier eine Binärdatei vorliegen, von der ich einen Teil einlese. D.h. ich habe eine Position in der Binärdatei an der ich meinen Lesezeiger positioniere, dann lese ich z.B. 4 Bytes ein, und diese möchte ich in eine andere Datei speichern. Wenn z.B. die 4 interessierenden Bytes 00 01 FF AA lauten, dann möchte ich in der neuen Datei so etwas wie "0x0001FFAA" stehen haben.

    ifstream my_file (strSourceFilePath, ios::binary); 
    my_file .seekg(32L);  //ab Offset 32 beginnt der interessierende Teil
    char my_buffer[4];  //ich bin an 4 Bytes interessiert
    my_file.read(my_buffer, 4); //4 Bytes aus der Datei in my_buffer einlesen
    

    Aber irgendwie funktioniert das ganz und gar nicht so, wie ich mir das vorstelle. Gibt es irgend eine Möglichkeit, eine Datei so einzulesen, dass quasi die Hex-Werte als ASCII gespeichert werden? Also z.B. wenn ich FF einlese, dass das dann auch als FF (ASCII) gespeichert wird damit ich es direkt in eine andere Datei schreiben kann?!

    Bin für Hilfe dankbar!



  • Du brauchst doch nur dein char-Array entsprechend rauszuschreiben. Wenn du die Hex-Zahlen dort drin haben willst, kannst du das doch mit Modifizierer hex machen.



  • Einlese und dann als Hex ausgeben.

    http://www.cppreference.com/io_flags.html#format_flags



  • Hallo nochmal,

    okay vielen Dank mal soweit. Ich habe jetzt in etwa so etwas:

    char my_buffer[4] = {0}; 
    ifstream dateilesen(...);
    dateilesen.get(my_buffer[0]); 
    dateilesen.get(my_buffer[1]); 
    dateilesen.get(my_buffer[2]); 
    dateilesen.get(my_buffer[3]); 
    								printf("buffer3: %x buffer2: %x buffer1: %x buffer0: %x", my_buffer[3], my_buffer[2], my_buffer[1], my_buffer[0]);
    

    Nur erhalte ich manchmal eine Ausgabe, die ich absolut nicht nachvollziehen kann. Und zwar kriege ich, wenn in der Datei z.B. "14 23 FF 54" steht, als Ausgabe "buffer3: 54 buffer2: ffffffff buffer1: 23 buffer0: 14"

    Das heißt er hat das zweite Element von my_buffer nicht mit "FF", sondern mit "ffffffff" gefüllt. Kann mir jemand sagen, woran das liegt?

    Danke für Hilfe.



  • Der Parameter wird beim Format %x als unsigned int interpretiert. Das könnte Probleme machen...?
    Da du C++ verwendest nimm besser cout << hex << buffer[0];



  • Hallo,

    danke für die Antwort. Tatsächlich scheint es etwas mit dem Vorzeichen zu tun zu haben. Wenn ich in der printf-Ausgabe den Inhalt des Arrays bei der Ausgabe jeweils mit static_cast in ein unsigned char umwandle funktioniert die Ausgabe. Aber wenn ich es mit dem << Operator in meine Datei schreiben will, bringt der Cast leider nichts. Unten stehend nochmal ein Teil meines Codes, die if-Abfrage soll dafür da sein dass ich jeweils eine führende kriege falls es sich um eine einstellige Hex-Zahl handeln sollte.

    Hat vielleicht noch jemand nen Tip?

    if(my_buffer[3] < 16)
        version_file << "0"; 
        dateilesen << uppercase << hex << static_cast<unsigned int>(my_buffer[3]);
    if(my_buffer[2] < 16)
        version_file << "0"; 
        dateilesen << uppercase << hex << static_cast<unsigned int>(my_buffer[2]);
    if(my_buffer[1] < 16)
        version_file << "0"; 
        dateilesen << uppercase << hex << static_cast<unsigned int>(my_buffer[1]);
    if(my_buffer[0] < 16)
        version_file << "0"; 
        dateilesen << uppercase << hex << static_cast<unsigned int>(my_buffer[0]);
    


  • caste besser nach unsigned char.



  • Wenn ich nach unsigned char caste, dann erhalte ich nicht lesbare Zeichen (z.B. 0x0000), da der modifizierer hex eine Zahl (z.B. int) erwartet.

    Also langsam dreh ich durch. Das kann doch nicht so schwer sein, eine Datei einzulesen, und dann in eine andere Datei das reinzuschreiben was ich eigentlich in einem Hexeditor sehen kann.

    Oder stehe ich einfach nur tierisch auf dem Schlauch?



  • Nene. unsigned int ist schon ok.
    Zeig mal das komplette (compilierbare) Programm.

    Du kannst auch:

    ...
    #include <iomanip>
    ...
    cout << hex << setfill('0') << setw(2) << static_cast<unsigned int>(buffer[i]);
    

    machen. Bedeutet: mindestens 2 Zeichen ausgeben und gegebenenfalls mit '0' auffüllen.



  • Also das mit dem setfill ist auf jeden Fall schon mal eine super Idee. Das werde ich dann noch einbauen. Der komplette Quellcode ist zu lang, deshalb mal hier ein kompilierbarer Ausschnitt.

    Wenn nun in der Datei "test.txt" ab Leseposition 16 so etwas wie "09 63 FF 01" steht, wird in "write_file" fälschlicherweise "ID: 0x010FFFFFFFF6309" geschrieben. Dass die Reihenfolge umgedreht ist, ist gewollt. Aber anstatt FF an zweiter Stelle schreibt er eben 0FFFFFFFF. Wobei die 0 bestimmt von meiner if-Schweinerei kommt. Also das eigentiche Problem sind die vielen F's 😡

    #include <fstream>
    #include <string>
    #include <iostream>
    
    using namespace std; 
    
    int main(void)
    {
    	ifstream read_file("test.txt"); 
    	ofstream write_file ("write_file.txt");
    	char my_buffer[4] = {0}; 
    
    	read_file.seekg(0L);
    	read_file.seekg(16L);
    	read_file.read(my_buffer, 4); 
    
    	write_file << "ID: 0x";
    	if(my_buffer[3] < 16)
    		write_file << "0"; 
    	write_file << uppercase << hex << static_cast<unsigned int>(my_buffer[3]);
    
    	if(my_buffer[2] < 16)
    		write_file << "0"; 
    	write_file << uppercase << hex << static_cast<unsigned int>(my_buffer[2]);
    
    	if(my_buffer[1] < 16)
    		write_file << "0"; 
    	write_file << uppercase << hex << static_cast<unsigned int>(my_buffer[1]);
    
    	if(my_buffer[0] < 16)
    		write_file << "0"; 
    	write_file << uppercase << hex << static_cast<unsigned int>(my_buffer[0]);
    
    	write_file.close();
    	read_file.close();
    
    }
    


  • Ok. Liegt am Datentyp. 0xFF passt zwar in den char rein. Erzeugt aber unerwünschte Ergebnisse.

    char 0xFF = -1
    wird zu
    unsigned int (unsigned int -1 = 0xFFFFFFFF)

    Also vorher auf unsigned char casten und es passt ;-).

    Mal ohne das drumherum:

    // mmh sieht komisch aus
    cout << static_cast<unsigned int>(static_cast<unsigned char>(buffer[i]));
    

    Einfacher ist es, wenn du gleich mit unsigned char buffer arbeitest.
    Evtl. musst du den dann beim .read casten.



  • Wow ist ja der Wahnsinn, es geht!! Unglaublich wie viel Zeit man manchmal mit solchen Kleinigkeiten verbringt.

    Von vornherein mit unsigned char arbeiten geht leider nicht. Aus irgend einem Grund kann der Compiler bei .read nicht casten so wie ich es will. Oder aber ich hab nen Schreibfehler drin 😃

    Auf jeden Fall vielen Dank für die Hilfe.

    Nun noch eine andere Frage: Ich lese immer wieder, dass es von schlechtem Stil zeugt, wenn man so viel in der Gegend rumcastet. Aber eine andere Idee hätte ich jetzt nicht gehabt für das was ich machen will.

    Oder gibt es einen vollkommen anderen Weg (mit C oder C++)?



  • naja, du könntest ja mal so versuchen:

    std::fstream stream("filename.bin", std::ios::in|std::ios::binary);
    unsigned char bytes[4];
    stream.read(reinterpret_cast<char *>( bytes ), 4 );
    

    Das sollte eigentlich funktionieren afaik



  • Gast56814 schrieb:

    Oder gibt es einen vollkommen anderen Weg (mit C oder C++)?

    Hi Bruder !
    Check this out:

    unsigned char c = 255;
    printf("%X", c );
    

    Analog dazu, um in eine Datei zu schreiben:

    fprintf( fp, "%X", c );
    

    🕶


Log in to reply