C++ String in Binärdatei speichern

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Affje800, 10. September 2013 .

Schlagworte:
  1. 10. September 2013
    Hallo,

    ich schreibe gerade ein Compiler-Backend, das vorhandenen Code in Java ByteCode übersetzt. Ich muss hierfür das ClassFile Byte für Byte schreiben und habe mir im Programmcode gewisse Hilfsfunktionen implementiert.

    Eine dieser Funktionen wandelt beispielsweise eine beliebige Zahl in eine Zahl im Hex-Format um, aus 15 wird 0F usw.
    Der Outputstream ist vom Typ ofstream und wird "binär geöffnet".
    Ich möchte jetzt dementsprechend den von der Hilfsfunktion erzeugten String in die Datei schreiben, doch statt 0x000D schreibt er mir stets 30 30 30 64 in die Datei.

    Ich möchte die Literale aber direkt schreiben, diese kann ich ja ganz einfach mit string.at(<position>) abfragen.

    Selbst mit

    Code:
    output << hex << s.(at(i);
    
    steht immer 30 30 30 64 statt 000D drin.
    Verschiedene reinterpret_casts waren auch erfolglos, ein Versuch mit output.wite(s.c_str(), length) ebenso.

    Wie schreibe ich denn das Literal/Zeichen direkt in die Datei, ohne Umwandlung?

    MfG
     
  2. 10. September 2013
    Zuletzt bearbeitet: 10. September 2013
    AW: C++ String in Binärdatei speichern

    Wieso wandelst du Zahlen in Hex-Zeichenketten um wenn du eh binär schreibst?
    Klar, dass du nacher 30 30 30 64 (= "000D") in der Datei stehen hast.

    Schreib 0x000D (= 13) als byte (= unsigned char) in die Datei.
     
    1 Person gefällt das.
  3. 10. September 2013
    Zuletzt von einem Moderator bearbeitet: 10. September 2013
    AW: C++ String in Binärdatei speichern

    Der output-Stream ist ja binär, wie du ja auch geschrieben hast. Dennoch steht beispielsweise bei output << 12; In der Datei dann 31 32, also einmal die 1 und einmal die 2.

    Ich habe auch noch eine Funktion DecToHex, die mir für einen beliebigen Int-Wert und eine Länge die Zahl in Hex-Form gibt.

    Code:
    const string ClassFile::DecToHex(int i, unsigned int length)
    {
     string r;
     ostringstream convert;
     convert << hex << i;
     r = convert.str();
     
     //Eventuell führende Nullen einfügen
     while (r.length() < length)
     {
     r.insert(0, "0");
     }
     return r;
    }
    
    Ich suche beim erstellen des Class-Files im Constant Pool nach Einträgen, die immer unterschiedliche Indizes haben, mal klein (1 Byte ausreichend), mal größer (2 Bytes).
    Der Eintrag muss in der Datei stets 2 Byte groß sein, daher habe ich mir gedacht, dass ich bei kleineren Werten eventuell Nullen in den String einfüge und dann quasi Character für Character in die Datei schreibe. Ich müsste jetzt noch was finden, was mir beispielsweise aus dem 000D jeweils Zweierpaare macht oder so, also 0x00 und 0x0D und das dann reinschreiben.

    Anfangs wird das Magic item geschrieben, das mache ich direkt:

    output << (char)0xCA;

    Wenn ich den Typecast weglasse, dann stimmt es auch nicht, deshalb mache ich das im obigen Posting genauso, leider ohne Erfolg.
    Irgendwo habe ich einfach nen riesen Denkfehler, danke trotzdem.
     
  4. 10. September 2013
    Zuletzt bearbeitet: 11. September 2013
    AW: C++ String in Binärdatei speichern

    ostream: perator<< ist auf jeden Fall schonmal falsch (generell wenn du bytes schreiben willst).
    Du brauchst ostream::write um binär zu schreiben.

    Ich habe von C++ nicht so die Ahnung, aber folgendes könnte funktonieren:

    Code:
    #include <fstream>
    #include <iostream>
    
    using std::ofstream;
    using std::ifstream;
    
    int main(void)
    {
     int num = 439041101;
     ofstream out { "./test.bin", ofstream::binary };
     
     size_t len = sizeof (int);
     size_t idx;
     
     std::cout << std::hex;
     
     for (idx = 0; idx < len; ++idx) {
     const char byte = num >> (idx * 8);
     std::cout << "schreibe byte " << (int)byte << std::endl;
     out.write(&byte, 1);
     }
     
     out.close();
     
     std::cout << std::dec;
     std::cout << "zahl geschrieben: " << num << std::endl;
     
     // ------------------------
     
     ifstream in { "./test.bin", ifstream::binary };
     
     char bin[len];
     in.read(bin, len); // 4 bytes einlesen (sizeof (int))
     in.close();
     
     int res = 0;
     
     std::cout << std::hex;
     
     // unten nach oben verarbeiten, da little-endian
     for (idx = len; idx > 0; --idx) {
     std::cout << "verarbeite byte " << (int)bin[idx - 1] << std::endl;
     res <<= 8;
     res |= bin[idx - 1];
     }
     
     std::cout << std::dec;
     std::cout << "zahl gelesen: " << res << std::endl;
     
     return 0;
    }
    
    
    In C geht das alles ein wenig einfacher, da man direkt binär (bzw. Speicher) schreiben/einlesen kann. Vielleicht macht es sogar Sinn das ganze mithilfe von extern "C" zu bewerkstelligen.

    Code:
    #include <stddef.h>
    #include <stdint.h>
    #include <stdio.h>
    
    int main(void)
    {
     FILE *fo, *fi;
     
     int32_t num = 439041101;
     int32_t res = 0;
     size_t len = sizeof (int32_t);
     
     fo = fopen("./test.bin", "w+b");
     fwrite(&num, 1, len, fo); /* jep, das wars schon */
     fclose(fo);
     
     fi = fopen("./test.bin", "rb");
     fread(&res, 1, len, fi); /* auch hier, einfach und effizient */
     fclose(fi);
     
     printf("geschrieben: %d, gelesen %d\n", num, res);
     return 0;
    }
    PS: Nichts für ungut, aber

    naja, von bits und bytes sollte man an dieser Stelle vielleicht schonmal gehört haben
    Zudem bekommst du es noch mit UTF-16 zu tun, das wird dann nochmal sehr lustig.
    Unter C++11 wohl gar nicht mehr so unangenehm.

    Keine Ahnung wie weit den Backend geht, aber ganz im ernst... binär in eine Datei schreiben ist das kleinste Problem.

    Dennoch viel Erfolg damit, ist ein spannendes Thema!
     
  5. 11. September 2013
    Zuletzt bearbeitet: 11. September 2013
    AW: C++ String in Binärdatei speichern

    Edit:

    Code:
    void ClassFile::writeIntToFile(int number, int length)
    {
     for (int i = 0; i < length; i++)
     {
     output.put(number >> (((length - 1) * 8) - i * 8) & 0xff); 
     }
    }
    
    writeIntToFile(13, 4);
    
    So funktionierts. aus 13 wird 00 00 00 0D.

    Danke nochmals.
     
  6. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.