Binärfile in vector<unsigned char> einlesen



  • Hiho,
    ich habe eine Frage:
    Gibt es eine effiziente Möglichkeit, eine Binärfile in einen std::vector<unsigned char> einzulesen?
    Bislang mache ich dies wie folgt

    std::fstream stream( fileName, std::ios::in | std::ios::binary );
    if( !stream )
    //Fehlerbehandlung + return
    
    //nur zur Beschleunigung im Debug
    size_t start = stream.tellg();
    stream.seekg( 0, std::ios::end );
    size_t end = stream.tellg();
    steam.seekg( 0, std::ios::beg );
    size_t size = end - start;
    
    char temp;
    unsigned char * pVals = new unsigned char[size + 1];
    
    for( int i = 0; stream; ++i )
    {
        stream.get( temp );
        pVals[i] = (unsigned char) temp;
    }
    
    std::vector<unsigned char> vec( pVals, pVals + size );
    delete [] pVals;
    pVals = NULL;
    

    Das Ganze mit dem Array ist eigentlich lediglich für die Beschleunigung des IOs im Debug Modus, da ein Vektor im Debug ziemlich viel Overhead erzeugt und von daher große Wartezeiten vorhanden sind, im Release wird das Ganze vermutlich geändert.
    Gibt es irgendwie eine schöne(re)/schnelle(re) Möglichkeit das Ganze zu bauen, oder ist dies eine der wenigen Möglchkeiten?
    thx so far



  • 1. Den Zwischenschritt über pTemp brauchst Du nicht. Du kannst auch direkt in pVals[i] einlesen.

    2. Den Zwischenschritt über pVals brauchst Du aber auch nicht. Lies direkt in die Vectorelemente ein.

    3. Mit einem istreambuf_iterator kannst Du - meine ich - auch direkt die Datei in den Vector "kopieren".

    vector<unsigned char> vec( (istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
    

    Beachte die zusätzlichen Klammern um das erste Argument. Sonst hast Du hinterher eine Funktion und keinen Vector 😉



  • hrmpf, joar, hatte bloß Probleme bei unsigned char Übergabe an stream.get();
    Das mit dem dynamisch allokierten Array habe ich ja bereits erwähnt, ist lediglich fürs Debugging, da sonst der Aufruf relativ lange dauert, da der vector im Debug ziemlich viel Overhead erzeugt.
    Die Sache mit dem istreambuf_iterator hat mir vorhin nicht gefallen (als ich sie zuvor schon im Debug-Mode ausprobiert habe, da das Einlesen einer einzelnen Datei hierbei ca 8 sec dauert), allerdings habe ich jetzt einmal Release kompiliert und es ist ziemlich eindeutig die schnellste Möglichkeit, das Ganze einzulesen (jedenfalls gemessen an meinen Tests).
    Thx so far

    EDIT:
    Da mir das ganze ein wenig zu lang gedauert hat (und es sich um eine zeitkritische Anwendung handelt), habe ich es nun wie folgt gelöst:

    //Größe der Datei ermitteln, wie im Original-Post
    std::vector<unsigned char> vec( size );
    stream.read( (char *) &vec[0], size );
    

    Ist das in Ordnung, also darf man das verwenden ohne, dass es irgendwo knallt?



  • Weiß nicht, warum du es nicht per Iterator machen willst, aber okay 😉

    std::ifstream stream(file_name.c_str(), std::ios_base::binary | std::ios_base::ate);
    if (!stream) return false;
    
    const std::size_t size(stream.tellg());
    stream.seekg(0, std::ios_base::beg);
    
    std::vector<unsigned char> data(size);
    stream.read(reinterpret_cast<char*>(&data[0]), size);
    

    sollte dann wohl so sein, wie du es haben willst.



  • Vorden schrieb:

    Ist das in Ordnung, also darf man das verwenden ohne, dass es irgendwo knallt?

    Oder kurz: Ja, darf man 😉


Anmelden zum Antworten