C++ binäres File einlesen

Darkko

Cadet 4th Year
Registriert
Juni 2011
Beiträge
64
hallo

mit folgendem code lese ich ein binäres file ein:

//read from binary file
cout << "Reading code from binary file..." << endl;
string binaryIn = "";
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) &binaryIn, sizeof(binaryIn));
inbin.close();

das funktioniert soweit auch, ausser dass es auf windows ab und zu zur meldung kommt, dass das programm nicht mehr reagiere. unter unix bekomme ich folgende meldung:

*** glibc detected *** corrupted double-linked list: 0xb7e15938 *** und nen backtrace

in allen fällen wird das file aber korrekt eingelesen und das programm läuft komplett durch inkl. den richtigen resultaten. trotzdem sind die oben genannten symptome etwas unschön. hat jemand eine idee woran es liegen könnte?
 
AW: [c++] binäres File einlesen

char binaryIn;
...
inbin.read((char*) &binaryIn, 1);

sollte funktionieren.
 
AW: [c++] binäres File einlesen

Ich hab's jetzt nicht kompiliert / getestet, aber das sollte funktionieren:

Code:
#include <fstream>
#include <iostream>
#include <vector>

typedef unsigned char byte;

int main()
{
	std::ifstream in( "huffmancompressed.bin", std::ios_base::in | std::ios_base::binary );

	if ( ! in )
	{
		std::cerr << "Konnte Datei nicht oeffnen!\n";
		return 1;
	}

	// Dateigroesse ermitteln
	in.seekg( 0, std::ios::end );
	const std::streamsize fileLength = in.tellg();

	if ( fileLength > 0 )
	{
		// zum Beginn der Datei zurückspulen
		in.seekg( 0, std::ios::beg );
		
		// vector erstellen, der groß genug ist, um Dateiinhalt aufzunehmen
		std::vector< byte > buffer( static_cast < std::size_t > ( fileLength ) );

		in.read( reinterpret_cast < char* > ( &buffer.front() ), fileLength );

		if ( ! in )
		{
			std::cerr << "Fehler beim Lesen!\n";
			return 1;
		}
		
		// Inhalt der eben ausgelesenen Datei auf Bildschirm ausgeben
		for ( std::size_t i = 0; i < buffer.size(); ++i )
		{
			std::cout << "Byte at index " << i << ": 0x" << std::hex << static_cast < unsigned int > ( buffer.at( i ) ) << std::dec << "\n";
		}
	}
	else
	{
		std::cerr << "Datei hat Groesse 0!\n";
	}
}
Ergänzung ()

Oder noch kürzer: :)

Code:
#include <fstream>
#include <iostream>
#include <vector>

typedef unsigned char byte;

int main()
{
	std::ifstream in( "huffmancompressed.bin", std::ios_base::in | std::ios_base::binary );

	if ( ! in )
	{
		std::cerr << "Konnte Datei nicht oeffnen!\n";
		return 1;
	}
	
	std::vector< byte > buffer( ( std::istreambuf_iterator< char >( in ) ), std::istreambuf_iterator< char >() );

	// Inhalt der eben ausgelesenen Datei auf Bildschirm ausgeben
	for ( std::size_t i = 0; i < buffer.size(); ++i )
	{
		std::cout << "Byte at index " << i << ": 0x" << std::hex << static_cast < unsigned int > ( buffer.at( i ) ) << std::dec << "\n";
	}
}
Ergänzung ()

Darkko schrieb:
in allen fällen wird das file aber korrekt eingelesen und das programm läuft komplett durch inkl. den richtigen resultaten. trotzdem sind die oben genannten symptome etwas unschön. hat jemand eine idee woran es liegen könnte?

Das liegt daran, daß du die read()-Methode aufs übelste belogen hast. :) Das erste Argument an diese Funktion sollte ein Zeiger auf den Beginn eines Speicherbereiches sein, in den die read()-Methode die gelesenen Daten legen soll. Du hast ihr die Anfangsadresse eines std::string-Objektes übergeben, aber so getan als wäre es die Adresse eines char-Arrays. Hättest du nicht gecastet (und damit gelogen), hätte dir dein Compiler gleich den Vogel gezeigt, denn für string-Objekte ist diese Methode überhaupt nicht gedacht.

read() wird einfach gnadenlos den Speicherbereich des string-Objektes überschreiben und damit das string-Objekt zerstören.
 
Zuletzt bearbeitet:
AW: [c++] binäres File einlesen

dank eurem input bin ich auf die lösung gekommen. eigentlich hat nur ein kleines detail nicht gepasst, wie antred schon erkannt hat:

cout << "Reading code from binary file..." << endl;
char* binaryIn;
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) &binaryIn, sizeof(binaryIn));
inbin.close();
string x =binaryIn;

@Ako a) ich caste von char* auf string und das geht b) es gibt einen unterschied zwischen sizeof() und size() auf ein string objekt ;)
 
Zuletzt bearbeitet:
AW: [c++] binäres File einlesen

Darkko schrieb:
dank eurem input bin ich auf die lösung gekommen. eigentlich hat nur ein kleines detail nicht gepasst:

Das glaube ich eher weniger. An deinem Code ist mehr als nur ein kleines Detail falsch.


Darkko schrieb:
cout << "Reading code from binary file..." << endl;
char* binaryIn;
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) &binaryIn, sizeof(binaryIn));
inbin.close();
string x =binaryIn;

Das soll gehen?? Glaub ich nicht. Erstens liest du damit nicht den kompletten Dateiinhalt sondern nur ein paar Zeichen (abhängig davon was sizeof( char* ) auf deinem System liefert). Zweitens schreibst du die gelesenen Daten in den Speicherbereich eines Pointers. Damit zeigt der Zeiger binaryIn dann irgend wo hin. Was an dem Speicherort, auf den binaryIn zeigt, dann liegt, ist purer Zufall.

Darkko schrieb:
b) es gibt einen unterschied zwischen sizeof() und size() auf ein string objekt ;)

Ja klar gibt es den ... das ist ja auch der Sinn der Sache. Bitte gehe deinen Code noch mal Zeile für Zeile durch und laß dir mal genau durch den Kopf gehen, was du da eigentlich tust.
 
AW: [c++] binäres File einlesen

Nein! Du hast es noch nicht verstanden. Dein Code kann doch so gar nicht funktionieren.

char* binaryIn; // definiert einen pointer auf char aber keinen Speicher für die einzulesenden chars.

inbin.read((char*) &binaryIn, sizeof(binaryIn)); // Hier wird in den pointer selbst gelesen!
sizeof(binaryIn) // ergibt je nach Architektur heutzutage meist 4 (32bit) oder 8(64bit) !

string x =binaryIn; // das ist Murks, da binaryIn ja als Pointer eine Adresse enthält, die du eben eingelesen hast.
 
AW: [c++] binäres File einlesen

doch, funktioniert tadellos:
sizeof(binaryIn) ist 4 (ok, ich hab echt keine ahnung wozu der parameter eigentlich gut sein soll)
gelesen werden 130 bits, die genau die binäre zahl repräsentieren die im bin file abgespeichert ist. der resultierende string ist 100111011... und mehr brauch ich nicht
 
AW: [c++] binäres File einlesen

Der Parameter gibt die Anzahl der zu lesenden Bytes an. 130 bits benötigen mindestens 17 Bytes. Ebenso :rolleyes:
 
AW: [c++] binäres File einlesen

ja ne, hilfe ist schon willkommen. nur funktioniert es jetzt halt und ich versteh nicht warum ihr der meinung seid, dass es nicht funktionieren könne.
kopiert es doch fix mal und probiert selber aus ;)
 
AW: [c++] binäres File einlesen

Schon getan. Stürzt wie erwartet sofort ab.

Wenn du wissen möchtest, warum wir der Meinung sind, weshalb das so nicht funktionieren kann, solltest du die Antworten, die man dir schreibt, vielleicht auch mal lesen.
 
AW: [c++] binäres File einlesen

ok, komisch. wenn ich das alleinstehend so versuche inkl dem schon erstellten bin file tut sich wirklich nichts (aber keine fehler oder absturz), aber wenn ich das file vorher im code erstelle, funktioniert es, warum? was mich auch zur nächsten frage bringt: ist es überhaupt sinnvoll eine binäre code-abfolge so in ein binäres file zu speichern?

//write to binary file
string binary="10101010101010101";
cout << "Writing code to binary file..." << endl;
cout << binary << endl;
cout << binary.size() << " bits written" << endl;
ofstream outbin("huffmancompressed.bin", ios::binary);
outbin.write((const char*) &binary, sizeof(binary));
outbin.close();

//read from binary file
cout << "Reading code from binary file..." << endl;
char* binaryIn;
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) &binaryIn, sizeof(binaryIn));
inbin.close();
cout << binaryIn << endl;
string x = binaryIn;
cout << x.size() << " bits read" << endl;
 
Zuletzt bearbeitet:
AW: [c++] binäres File einlesen

Darkko schrieb:
ok, komisch. wenn ich das alleinstehend so versuche inkl dem schon erstellten bin file tut sich wirklich nichts (aber keine fehler oder absturz), aber wenn ich das file vorher im code erstelle, funktioniert es, warum? was mich auch zur nächsten frage bringt: ist es überhaupt sinnvoll eine binäre code-abfolge so in ein binäres file zu speichern?

//write to binary file
string binary="10101010101010101";
cout << "Writing code to binary file..." << endl;
cout << binary << endl;
cout << binary.size() << " bits written" << endl;
ofstream outbin("huffmancompressed.bin", ios::binary);
outbin.write((const char*) &binary, sizeof(binary));
outbin.close();

//read from binary file
cout << "Reading code from binary file..." << endl;
char* binaryIn;
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) &binaryIn, sizeof(binaryIn));
inbin.close();
cout << binaryIn << endl;
string x = binaryIn;
cout << x.size() << " bits read" << endl;

Langsam frage ich mich, ob du mich ärgern willst. :p Du machst schon wieder den gleichen Mist, von dem ich dir weiter oben schon mal erklärt habe, weshalb er nicht funktioniern kann.

string binary="10101010101010101";
...
outbin.write((const char*) &binary, sizeof(binary));


Was du hier tust, ist den Inhalt des Speicherbereichs, den das std::string-Objekt namens binary belegt, in eine Datei rauszuschreiben. Was glaubst du, liegt in diesem Speicherbereich so alles??
 
AW: [c++] binäres File einlesen

ka was dort alles so liegen mag und warum es so denn überhaupt geht... hab kein plan mehr :D
also wenn ich so schreib:

//write to binary file
string binary = "10101010110101";
char * binaryx =new char[binary.size()];
for(int i=0;i<binary.size();i++){
binaryx=binary.at(i);
}
cout << "Writing code to binary file..." << endl;
cout << binaryx << endl;
cout << binary.size() << " bits written" << endl;
ofstream outbin("huffmancompressed.bin", ios::binary);
outbin.write((const char*) binaryx, binary.size());
outbin.close();

//read from binary file
cout << "Reading code from binary file..." << endl;
char* binaryIn = new char[binary.size()];
ifstream inbin("huffmancompressed.bin", ios::binary);
inbin.read((char*) binaryIn, binary.size());
inbin.close();
cout << binaryIn << endl;
string x = binaryIn;
cout << x.size() << " bits read" << endl;

wäre das jetzt besser? so funktioniert der read block auch standalone. warum das ganze aber auch vorhin mit dem string und dessen speicherbereich einwandfrei funktionierte (nur wenn write und read zusammen ausgeführt wurden) versteh ich immer noch nicht.
 
Zuletzt bearbeitet:
AW: [c++] binäres File einlesen

Lies dir mal das hier durch.
Unten ist der Teil zu binarys, lies aber lieber alles.
Dass dein Code funktioniert ist reines Glück.
Du reservierst keinen Speicher, trickst mit Casts rum, verwechselst Pointer mit den dazugehörigen Referenzen.
Schau dir deshalb besser auch nochmal an, wie Pointer und die Speicherverwaltung in C++ funktioniert.
 
Zurück
Oben