Datei binär schreiben lesen

Krikus

Mitglied
Hi,

ich muss in einer Datei Namen von Personen binär abspeichern.
Dies klappt auch bereits.
Wie kann ich allerdings diese Namen wieder einlesen, sodass ich z.B die Ausgabe so gestalten könnte:

1. Name:
2. Name:


Hier einmal mein Code:

C++:
// dateihandler.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <string>
#include <fstream>   // wg. Dateioperationen
using namespace std;

void einlesen()
{
	ifstream start;                        
	start.open("namen.dat", ios::in|ios::binary);  
	if (!start) {                 // Datei kann nicht geoeffnet werden
			 cerr << "namen.dat" << " kann nicht geöffnet werden!\n";
			 exit(-2);
	 }
	//eingabe.read((char *)&d, sizeof(d));        
	//eingabe.close(); 
}

void schreiben(string x)
{
	    ofstream ziel;                 // Zieldatei (Schreiben)
		ziel.open("namen.dat", ios::out|ios::app|ios::binary); // zum Schreiben öffnen
        if (!ziel) {                   // Datei kann nicht geoeffnet werden
                cerr << "namen.dat" << " kann nicht geöffnet werden!\n";
                exit(-2);
        }
		ziel.write((char *)&x, sizeof(x));   
		//ziel.close(); kann weggelassen werden, da in Funktionen automatisch geschlossen wird
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	string test;
	cout << "Namen eingeben"<<endl;
	cin >> test;
	schreiben(test);
			
    getch();
	return 0;
}
 
Zuletzt bearbeitet von einem Moderator:
Hi,

ich muss in einer Datei Namen von Personen binär abspeichern.
Dies klappt auch bereits.
Das ist ein Irrtum. Hast du mal in die Datei geschaut? Oder wie groß die Datei ist?

Du mußt schon direkt die Daten in die Datei schreiben, und nicht einfach die Adresse eines Funktionsparameters. Diese Adresse ist nämlich bereits nach Verlassen der Funktion wieder ungültig, vor allem nach einem Neustart des Programmes.
C++:
string s;

ziel.write(s.data(), s.size());
Es wäre evtl. eine gute Idee, die Strings so zu speichern, das du zuerst die Länge als int in die Datei schreibst und dann die Daten des Strings, so dass du nachher beim Einlesen die Information über die Länge der Daten hast und diese direkt Einlesen kannst:
C++:
int size;
start.read(reinterpret_cast<char*>(&size), sizeof(size));

char* s = new char[size];
start.read(s, size);
Fehlerbehandlung bzw. Überprüfung des Einlesens lass ich mal weg. Evlt. solltest du auch einfach mal nach anderen Themen hier suchen.

Gruß
 
Danke für deineAntwort.
Hab es jetzt einmal umgebaut.
Soweit wie ich das nun beurteilen kann, läuft es auch.
Allerdings habe ich mit der Ausgabe noch ein Problem. Diese gibt mir natürlich nur den ersten Datensatz aus. Wie kann ich in einem Rutsch alle Datensätze aufeinmal aus der Datei einlesen und ausgeben?

C++:
struct start_destination
{
	char start[50];
    char destination[50];
};


void write_binary_file(start_destination p_Data)
{       
	ofstream binary_file;// Zieldatei (Schreiben)
	binary_file.open("test.dat", ios::out|ios::app|ios::binary); // zum Schreiben öffnen
	if (!binary_file) {                   // Datei kann nicht geoeffnet werden
		cerr << "test.dat" << " kann nicht geoeffnet werden!\n";
		getch();
	} 
	binary_file.write(reinterpret_cast<char *>(&p_Data),sizeof(start_destination));
	binary_file.close();
}

void read_binary_file()
{
	start_destination p_Data;
	ifstream binary_file;                        
	binary_file.open("test.dat", ios::in|ios::binary);  
	if (!binary_file) {                 // Datei kann nicht geoeffnet werden
		cerr << "test.dat" << " kann nicht geoeffnet werden!\n";
		getch();
	}
	binary_file.read(reinterpret_cast<char *>(&p_Data),sizeof(start_destination));
	binary_file.close();

	cout<<"Start: "<<p_Data.start<<endl;
	cout<<"Destination :"<< p_Data.destination<<endl;

}
 
Zuletzt bearbeitet von einem Moderator:
Moin,

beispielsweise so:
Code:
FILE *stream;
long  numread = 0;
int iFileHandle = 0;
rsp_datalen = 0;
iFileHandle = _access(strFileName, 0);
if( iFileHandle != -1)
{
    iFileHandle = _sopen (strFileName, _O_RDONLY, _SH_DENYNO);
    if (iFileHandle != -1)
    {
        numread = _lseek( iFileHandle, 0L, SEEK_END );
        _close(fh);
// in "numread" steht jetzt die Anzahl der zu lesenden Zeichen
    }
}

Jetzt weißt an der Stelle also, wieviele Zeichen insgesamt zu lesen sind!
Nutze entweder den Tipp von deepthroat, jeweils die Länge der einzelnen Namen mit abzuspeichern, oder speichere ein beliebiges Trennzeichen (etwa ';' oder '#') nach jedem Namen. Im letzteren Fall kannst Du dann sogar bequem über RegEx splitten!

Gruß
Klaus
 
Hi.
Danke für deineAntwort.
Hab es jetzt einmal umgebaut.
Aber warum auf diese Weise? Da verschwendest du jetzt einen Haufen Speicher und bist natürlich auch nicht flexibel. Warum bleibst du denn nicht bei den std::strings?
Allerdings habe ich mit der Ausgabe noch ein Problem. Diese gibt mir natürlich nur den ersten Datensatz aus. Wie kann ich in einem Rutsch alle Datensätze aufeinmal aus der Datei einlesen und ausgeben?
Am einfachsten implementierst du je eine Funktion die einen Stream und einen String übergeben bekommt. So kannst du die Datei öffnen und für jeden Datensatz die Funktion aufrufen:
C++:
bool read_data(istream& in, was_auch_immer& data) {
  was_auch_immer temp;

  if (in.read(reinterpret_cast<char*>(&temp, size?)) {
    data.swap(temp);
    return true;
  } else return false;
}

ifstream file("abc.dat", ios::binary | ios::in);
was_auch_immer entry;
while (read_data(file, entry)) {
  // Ausgabe von entry
}
@vfl_freak: Warum sollte man das denn unbedingt auf diese Weise machen und alles komplett in den Speicher lesen? Wozu sollte man die Lowlevel Funktionen statt der iostreams verwenden?

Gruß
 
Moin,

@vfl_freak: Warum sollte man das denn unbedingt auf diese Weise machen und alles komplett in den Speicher lesen? Wozu sollte man die Lowlevel Funktionen statt der iostreams verwenden?

Wer sagt denn was unbedingt nur so ? ? ?
Ich hatte geschrieben: beispielweise so ! ! !

Sicher kann man es auch anders lösen .... das hängt ja vielleicht auch ein bisschen davon ab, was man mit dem eingelesenen Daten machen will, oder nicht

Gruß
Klaus
Gruß
Klaus
 
Wer sagt denn was unbedingt nur so ? ? ?
Ich hatte geschrieben: beispielweise so ! ! !
Dann frage ich anders: wie kommst du auf die Idee es ausgerechnet so (und nicht anders; sprich: einfacher und plattformunabhängig) zu machen?

Ich schätze ein Anfänger wüßte jetzt gar nicht was er mit deinem Code überhaupt anfangen sollte...

Gruß
 
Moin,

Dann frage ich anders: wie kommst du auf die Idee es ausgerechnet so (und nicht anders; sprich: einfacher und plattformunabhängig) zu machen?
Weil das hier in dem Projekt, was ich übernommen habe, ein einer der vielen Hilfsfunktionen so steckt! Sicher kann man das auch anders (einfacher) machen, aber bei über 60.000 Zeilen bleibt sowas dann meist einfach drin mit den lapidaren Hinweis: historisch gewachsen! :(

Plattformunabhängigkeit ist hier bei uns eh' nicht das Thema .....

Und man halt i. d. R. nicht die Zeit, um Dinge die funktionioeren zu anderen Dingen umzubauen, die genauso funktionieren .....

Ich schätze ein Anfänger wüßte jetzt gar nicht was er mit deinem Code überhaupt anfangen sollte...
Ok, das mag sein, aber zum einen gibt es dann dafür Hilfen und zum anderen wage ich dann zu bezweifeln, dass ein Anfänger so auf Abhieb weiß, was bspw. ein "reinterpret_cast" ist.

Wir formulieren hier doch meist alle unsere Antworten mehr nach dem eigenen Wissensstand, zumal ja auch meist nicht klar ist, was ein Fragesteller weiß und was nicht ....

Gruß
Klaus
 
Ok, das mag sein, aber zum einen gibt es dann dafür Hilfen und zum anderen wage ich dann zu bezweifeln, dass ein Anfänger so auf Abhieb weiß, was bspw. ein "reinterpret_cast" ist.
Die Bedeutung eines Schlüsselwortes kann man relativ schnell nachschauen, aber einen (etwas) komplexeren Codeschnipsel überschaut man nicht so schnell.
Wir formulieren hier doch meist alle unsere Antworten mehr nach dem eigenen Wissensstand, zumal ja auch meist nicht klar ist, was ein Fragesteller weiß und was nicht ....
Das mag sein, aber da kann man auch nicht davon ausgehen, das ein Fragesteller ein Windows Betriebssystem einsetzt... ;)

Außerdem finde ich es bedenklich Anfängern Code an die Hand zu geben, der (evtl.) selbst nicht richtig verstanden wird, nur in der Form verwendet wird weil historisch so gewachsen / von irgendjemand mal so geschrieben, Sicherheitsprobleme verursacht bzw. einfach falsch ist.

Wenn man hier Antworten postet, sollte man doch darauf achten, das Anfänger dazu neigen den hier präsentierten Code als "das gelbe vom Ei" zu betrachten und das sich auf diese Weise manche Irrtümer und schlechte Angewohnheiten verbreiten.

Gruß
 
Hatte jetzt wieder zeit mich meinem Problem zu widmen.
Meine Funktion gibt mir nun alle Einträge aus, allerdings wird der letzte Eintrag doppelt ausgegeben.

C++:
void read_from_binary_file()
{
	start_destination p_Data;
	ifstream binary_file;                        
	binary_file.open("test.dat", ios::in|ios::binary);  
	if (!binary_file) {                 // Datei kann nicht geoeffnet werden
		cerr << "test.dat" << " kann nicht geoeffnet werden!\n";
		getch();
	}
    while (!binary_file.eof()) {  
		binary_file.read(reinterpret_cast<char *>(&p_Data),sizeof(start_destination));

		cout<<"Start: "<<p_Data.start<<endl;
		cout<<"Destination :"<< p_Data.destination<<endl;
	}
	binary_file.close();

}
 
Zuletzt bearbeitet von einem Moderator:
Zurück