Binäre Datei schreiben und lesen



  • Ich muss relativ dringend einen Programmteil schrieben der binäre Dateien schreibt und wieder einlesen kann. Leider funktioniert das nicht, obwohl es meiner Meinung nach sollte. Deshalb ist mir nicht klar was an meinem kurzen Programm falsch ist:

    #ifndef SIMPLEBINARYFILEHANDLING_H
    #define SIMPLEBINARYFILEHANDLING_H
    
    #include <string>
    #include <sstream>
    #include <iostream>
    
    #include <stdio.h>
    
    class SimpleBinaryFileHandling {
    
    	public:
    	static const int stringLength = 10;
    	void run();
    	void write2File( std::string filename );
    	void readFromFile( std::string filename );
    
    };
    
    #endif
    
    #include "SimpleBinaryFileHandling.h"
    
    using namespace std;
    
    void SimpleBinaryFileHandling::run() {
    	cout << "write2File" << endl;
    	write2File( "binary.data" );
    	cout << "readFromFile" << endl;
    	readFromFile( "binary.data" );
    	cout << "done" << endl;
    }
    
    void SimpleBinaryFileHandling::write2File( std::string filename ) {
    	char buffer[sizeof(int)+stringLength];
    
    	int number = 10;
    	string text = "text12";
    
    	char* bufferPointer;
    	memcpy( bufferPointer, &number, sizeof(int) );
    	bufferPointer += sizeof(int);
    
    	memcpy( bufferPointer, text.c_str(), stringLength );
    
    	//Schreibe den Puffer in eine Datei
    	FILE* file;
    	file = fopen( filename.c_str(), "wb");
    	fwrite( buffer, sizeof(int)+stringLength, 1, file );
    	fclose(file);
    
    }
    
    void SimpleBinaryFileHandling::readFromFile( std::string filename ) {
    
    	FILE* infile = NULL;
    	infile = fopen( filename.c_str(), "rb" );
    	fseek( infile, 0, SEEK_END );
    	int fileSize = ftell( infile );
    	// return the file pointer to begin of file if you want to read it
    	rewind( infile );
    	char binData[fileSize];
    	fread( binData, fileSize, 1, infile );
    	fclose( infile );
    
    	int number;
    	char text[stringLength];
    	char* binDataPointer = binData;
    	memcpy( &number, binDataPointer, sizeof(int) );
    	binDataPointer += sizeof(int);
    
    	memcpy( text, binDataPointer, stringLength );
    
    	cout << "number = " << number << endl;
    	cout << "text = " << text << endl;
    
    }
    

    Als Ausgabe kommt dann sowas zB raus:

    ./Play
    write2File
    readFromFile
    number = -1284926560
    text = ?
    done
    Segmentation fault


  • Mod

    Entscheide dich mal für C oder C++. So können dir weder die C'ler noch die C++'ler helfen, weil beide das Kotzen bekommen, wenn Sie deinen Quelltext sehen und dir nur empfehlen werden, dass es an der Mischung der Sprachen liegt (höchstwahrscheinlich tut es das auch).



  • Das liegt wahrscheinlich wohl auch daran, dass man bei Google 1000 "Tutorials" findet die einfach mal immer alles durcheinanderschmeißen...



  • Man lernt C++ auch nicht anhand einiger Tutorials.
    Normalerweise kauft man sich mind. ein gutes Buch wie z.b. den Primer und liest den sorgfältig durch. Alles andere macht wenig Sinn und das Resultat siehst du ja.


  • Mod

    HändyÄndy schrieb:

    Das liegt wahrscheinlich wohl auch daran, dass man bei Google 1000 "Tutorials" findet die einfach mal immer alles durcheinanderschmeißen...

    Ja, Internettutorials kannste vergessen. Die werden von Anfängern geschrieben die erste Erfolge hatten und sich nun für gut halten. Selbst viele Lehrbücher fallen in den Bereich "gefährliches Halbwissen". Aber ich bin mir nicht einmal sicher, ob du nun C oder C++ machen willst, daher kann ich auch nichts empfehlen, außer tunlichst eine Mischung zu vermeiden, solange du noch nicht genau weißt, was du da tust.



  • Hab nochmal gegooglet und denke, dass ich nun was rein C++-mäßiges gefunden habe: http://www.codersource.net/c/c-tutorial-on-file-operations/c-file-i-o-binary-files-using-fstream.aspx (will nämlich C++ machen). Deshalb sieht mein Code jetzt so aus:

    #ifndef SIMPLEBINARYFILEHANDLING_H
    #define SIMPLEBINARYFILEHANDLING_H
    
    #include <string>
    #include <sstream>
    #include <iostream>
    #include <fstream>
    
    #include <stdio.h>
    
    class BinaryObject {
    
    	public:
    	BinaryObject();
    	BinaryObject( std::string text, int number );
    	static const int textLength = 10;
    	char text[textLength];
    	int number;
    
    };
    
    class SimpleBinaryFileHandling {
    
    	public:
    	static const int stringLength = 10;
    	void run();
    
    	void writeBinaryObject();
    	void readBinaryObject();
    
    };
    
    #endif
    
    #include "SimpleBinaryFileHandling.h"
    
    using namespace std;
    
    BinaryObject::BinaryObject() {}
    
    BinaryObject::BinaryObject( string text_, int number_ ) {
    	if( text_.length() < textLength-1 ) {
    		text = text_.c_str();
    		text[textLength-1] = '\0';
    	} else {
    		cout << "Text ist zu lang und wird beschnitten auf " << text_.substr(0,textLength-1) << endl;
    		text = text_.substr(0,textLength-1).c_str();
    		text[textLength-1] = '\0';
    	}
    	number = number_;
    }
    
    void SimpleBinaryFileHandling::run() {
    	cout << "write2File" << endl;
    	writeBinaryObject();
    	cout << "readFromFile" << endl;
    	readBinaryObject();
    	cout << "done" << endl;
    }
    
    void SimpleBinaryFileHandling::writeBinaryObject() {
    	cout << "sizeof(BinaryObject) = " << sizeof( BinaryObject ) << endl;
    	BinaryObject bo1( "Objekt1", 1 );
    	BinaryObject bo2( "Objekt2", 2 );
    
    	fstream binary_file( "binary.data", ios::out | ios::binary );
    	binary_file.write( reinterpret_cast<char *>(&bo1), sizeof(BinaryObject) );
    	binary_file.write( reinterpret_cast<char *>(&bo2), sizeof(BinaryObject) );
    	binary_file.close();
    }
    
    void SimpleBinaryFileHandling::readBinaryObject() {
    
    	BinaryObject bo1;
    	BinaryObject bo2;
    	fstream binary_file("binary.data", ios::binary | ios::in);
    	binary_file.read( reinterpret_cast<char *>(&bo1), sizeof(BinaryObject) );
    	binary_file.read( reinterpret_cast<char *>(&bo2), sizeof(BinaryObject) );
    	binary_file.close();
    
    }
    

    Geht leider auch nicht so wie ich es erwarte.
    1. sizeof( BinaryObject ) ist 16. Macht für mich überhaupt keinen Sinn, denn ich habe einen int und ein char[10] in der Klasse. Ich würde also als Ergebnis 14 erwarten.

    2. text = text_.c_str(); gibt eine Compiler Fehlermeldung. Ich kann keinen String variabler Länge in eine Binarydatei reinschreiben, deshalb muss ich wohl den Text auf max. 10 Zeichen stutzen. Das geht so aber scheinbar nicht.

    Hat jemand ein paar Tipps für mich?



  • HändyÄndy schrieb:

    1. sizeof( BinaryObject ) ist 16. Macht für mich überhaupt keinen Sinn, denn ich habe einen int und ein char[10] in der Klasse. Ich würde also als Ergebnis 14 erwarten.

    Nennt sich Padding.

    2. text = text_.c_str(); gibt eine Compiler Fehlermeldung. Ich kann keinen String variabler Länge in eine Binarydatei reinschreiben, deshalb muss ich wohl den Text auf max. 10 Zeichen stutzen. Das geht so aber scheinbar nicht.

    Das liegt daran, dass c_str einen const char zurückgibt. Aber das Problem wirst du ganz schnell los, wenn du aus char text[textLength] ein string text machst.


  • Mod

    HändyÄndy schrieb:

    Hab nochmal gegooglet und denke, dass ich nun was rein C++-mäßiges gefunden habe: http://www.codersource.net/c/c-tutorial-on-file-operations/c-file-i-o-binary-files-using-fstream.aspx (will nämlich C++ machen). Deshalb sieht mein Code jetzt so aus:

    Es gehört mehr zu C++ als nur fstream zu benutzen. Und wie dir auch schon gesagt wurde, lernt man mit Google keine Sprachen. Du (und dein neuester Quelltext) sind die besten Beispiele. Wilde Mischung von Sprachen, kein Konzept, kein Verständnis für das was du tust. Klingt hart, aber es bringt ja nichts, aus Höflichkeit die Dinge nicht beim Namen zu nennen.

    Geht leider auch nicht so wie ich es erwarte.
    1. sizeof( BinaryObject ) ist 16. Macht für mich überhaupt keinen Sinn, denn ich habe einen int und ein char[10] in der Klasse. Ich würde also als Ergebnis 14 erwarten.

    Das erwartest du falsch. Stichworte zum selber Nachschlagen (dafür ist Google gut!): Padding, Alignment

    2. text = text_.c_str(); gibt eine Compiler Fehlermeldung. Ich kann keinen String variabler Länge in eine Binarydatei reinschreiben, deshalb muss ich wohl den Text auf max. 10 Zeichen stutzen. Das geht so aber scheinbar nicht.

    Arrays haben keine Kopiersemantik. In C++ bräuchtest du keine Arrays, in C müsstest du so etwas wissen.

    Hat jemand ein paar Tipps für mich?

    Lern die Sprache! Und zwar richtig! Dir mag hier keiner helfen, wenn du mit irgendwelchem total komplizierten Speicherrumgepfusche ankommst, aber noch nicht einmal einfachste Grundlagen versteht.



  • Okay, welches Buch empfehlt Ihr denn? Vorkenntnisse hab ich ja schon und meine Programm laufen ohne Speicherlecks und Segfaults. Blutiger Anfänger bin ich wohl nicht mehr. Bücher in denen ne for-Schleife erklärt wird will ich nicht lesen.



  • Der C++ Programmierer

    mfg, René~



  • HändyÄndy schrieb:

    Ich muss relativ dringend einen Programmteil schrieben der binäre Dateien schreibt und wieder einlesen kann.

    Warun so kompliziert. Wenn Du einfach eine Zeichenfolge in eine Datei schreiben und wieder daraus lesen willst, so geht das einfacher mit:

    #include <algorithm> // copy
    #include <fstream>
    #include <iostream>
    #include <iterator> // i/ostreambuf_iterator
    #include <string>
    
    int main()
    {
        using namespace std;
        {
            // --   Schreiben
            string text = "Das ist ein Text\nmit\tSteuerzeichen\n";
            ofstream file( "binary.data", ios_base::binary );
            copy( text.begin(), text.end(), ostreambuf_iterator< char >( file ) );
        }
        // --   Lesen
        ifstream in( "binary.data", ios_base::binary );
        if( !in.is_open() )
        {
            cerr << "Fehler beim Oeffnen der Datei" << endl;
            return -1;
        }
        string read_text( (istreambuf_iterator< char >( in )), istreambuf_iterator< char >() );
        cout << read_text << endl;
        return 0;
    }
    

    Aber ich glaube, dass in 'char text[textLength];' gar keine Zeichenfolge, sondern irgend etwas anderes drinsteht - oder?

    In Zeile 19

    HändyÄndy schrieb:

    char* bufferPointer;
    

    wird bufferPointer nicht initialisiert.

    Gruß
    Werner



  • NewSoftzzz schrieb:

    Der C++ Programmierer

    Stimmt es, dass da auch GUI, Netzwerk- und Threadprogrammierung behandelt werden? Falls ja, wäre ich erst mal skeptisch. Dazu muss man sich einerseits auf eine bestimmte Bibliothek festlegen, welche je nachdem mehr oder weniger nützlicher für den Programmierer ist. Andererseits kommt C++ selbst bei solchen Büchern oft zu kurz.



  • Nexus schrieb:

    NewSoftzzz schrieb:

    Der C++ Programmierer

    Stimmt es, dass da auch GUI, Netzwerk- und Threadprogrammierung behandelt werden? Falls ja, wäre ich erst mal skeptisch. Dazu muss man sich einerseits auf eine bestimmte Bibliothek festlegen, welche je nachdem mehr oder weniger nützlicher für den Programmierer ist. Andererseits kommt C++ selbst bei solchen Büchern oft zu kurz.

    Aufgrund des Inhaltsverzeichnisses kommt im Buch Qt und Boost vor.
    $imon


Log in to reply