tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
12
ZUGRIFFE
1657
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Krikus Krikus ist offline Mitglied Silber
    Registriert seit
    Jan 2009
    Beiträge
    64
    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:

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    // 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;
    }
     

  2. #2
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von Krikus Beitrag anzeigen
    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.
    Code cpp:
    1
    2
    3
    
    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:
    Code cpp:
    1
    2
    3
    4
    5
    
    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ß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  3. #3
    Krikus Krikus ist offline Mitglied Silber
    Registriert seit
    Jan 2009
    Beiträge
    64
    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?

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    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;
     
    }
     

  4. #4
    Avatar von vfl_freak
    vfl_freak vfl_freak ist offline Mitglied Diamant
    Registriert seit
    Aug 2007
    Ort
    Niedersachsen
    Beiträge
    2.161
    Moin,

    beispielsweise so:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    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
     
    Es ist noch kein Meister vom Himmel gefallen - sonst hätte man schon längst seine Leiche gefunden !!

    Falls ich helfen konnte, wäre eine Bewertung oder ein Danke nett ;-)
    -------------------------------------------------------------------------------------------------
    Ich beantworte keine Fragen per PN !!
    Stellt Eure Fragen im Forum - dann haben alle etwas davon !!

  5. #5
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.
    Zitat Zitat von Krikus Beitrag anzeigen
    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?
    Zitat Zitat von Krikus Beitrag anzeigen
    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:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    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ß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  6. #6
    Avatar von vfl_freak
    vfl_freak vfl_freak ist offline Mitglied Diamant
    Registriert seit
    Aug 2007
    Ort
    Niedersachsen
    Beiträge
    2.161
    Moin,

    Zitat Zitat von deepthroat Beitrag anzeigen
    @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
     
    Es ist noch kein Meister vom Himmel gefallen - sonst hätte man schon längst seine Leiche gefunden !!

    Falls ich helfen konnte, wäre eine Bewertung oder ein Danke nett ;-)
    -------------------------------------------------------------------------------------------------
    Ich beantworte keine Fragen per PN !!
    Stellt Eure Fragen im Forum - dann haben alle etwas davon !!

  7. #7
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von vfl_freak Beitrag anzeigen
    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ß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  8. #8
    Avatar von vfl_freak
    vfl_freak vfl_freak ist offline Mitglied Diamant
    Registriert seit
    Aug 2007
    Ort
    Niedersachsen
    Beiträge
    2.161
    Moin,

    Zitat Zitat von deepthroat Beitrag anzeigen
    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 .....

    Zitat Zitat von deepthroat Beitrag anzeigen
    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
     
    Es ist noch kein Meister vom Himmel gefallen - sonst hätte man schon längst seine Leiche gefunden !!

    Falls ich helfen konnte, wäre eine Bewertung oder ein Danke nett ;-)
    -------------------------------------------------------------------------------------------------
    Ich beantworte keine Fragen per PN !!
    Stellt Eure Fragen im Forum - dann haben alle etwas davon !!

  9. #9
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von vfl_freak Beitrag anzeigen
    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.
    Zitat Zitat von vfl_freak Beitrag anzeigen
    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ß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  10. #10
    Krikus Krikus ist offline Mitglied Silber
    Registriert seit
    Jan 2009
    Beiträge
    64
    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.

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    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();
     
    }
     

  11. #11
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.
    Zitat Zitat von Krikus Beitrag anzeigen
    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.
    Ach, es ist immer wieder das gleiche. Und da hab ich es dir schon vorgemacht...

    Nicht so:
    Code cpp:
    1
    2
    
        while (!binary_file.eof()) {  
            binary_file.read(reinterpret_cast<char *>(&p_Data),sizeof(start_destination));
    Sondern so:
    Code cpp:
    1
    
    while (binary_file.read(reinterpret_cast<char *>(&p_Data),sizeof(start_destination)) {
    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  12. #12
    Krikus Krikus ist offline Mitglied Silber
    Registriert seit
    Jan 2009
    Beiträge
    64
    Hi,

    ich hab den code ein bisschen erweitert, bzw. in eine Klasse eingebaut.
    Bevor ich nun einen neuen Thread aufmache poste ich es hier.
    Das schreiben an sich klappt. Allerding wird der Name des Ortes nicht gespeichert.
    Anscheined klappt bei der Umwandlung von string in char etwas nicht.
    Die get-Methode "get_name" liefert einen String mit dem Namen des Ortes zurück.
    Hier einmal der Code.

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    void write_to_binary_file()
    {       
        struct daten
        {
            char test[30];
            int x_ko;
            int y_ko;
        };
        daten p_daten;
     
        const char *x;
        struct knoten *p = anfang;  
        ofstream binary_file;// Zieldatei (Schreiben)
        binary_file.open("binaer.dat", ios::out|ios::binary); // zum Schreiben öffnen
        if (!binary_file) {                   // Datei kann nicht geoeffnet werden
            cerr << "binaer.dat" << " kann nicht geoeffnet werden!\n";
            getch();
        }
        while (p != NULL) {                        
                        x = p->info.get_name().c_str();//string zu char umwandeln
                        strcpy( p_daten.test, x);
                        p_daten.x_ko = p->info.get_x_koordinate();
                        p_daten.y_ko = p->info.get_y_koordinate();
                        binary_file.write(reinterpret_cast<char *>(&p_daten),sizeof(daten));
                        p = p->next;                 // p auf Folgeelement setzen
                }
     
        binary_file.close();
    }
     

  13. #13
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.
    Zitat Zitat von Krikus Beitrag anzeigen
    Code cpp:
    1
    2
    
                        x = p->info.get_name().c_str();//string zu char umwandeln
                        strcpy( p_daten.test, x);
    Das geht so nicht. Die get_name() Methode liefert ein temporäres Objekt. Die c_str() Methode liefert einen entsprechenden Zeiger auf die Daten dieses temporären Objektes den du dann speicherst.

    Das temporäre Objekt wird üblicherweise gleich wieder weggeräumt, so das du einen ungültigen Zeiger hast.

    Vermeide die Verwendung von Zeigern.

    Code cpp:
    1
    
    strcpy(p_daten.test, p->info.get_name().c_str());
    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

Ähnliche Themen

  1. Binär struct tm schreiben und lesen?!
    Von Metzlmane im Forum C/C++
    Antworten: 7
    Letzter Beitrag: 13.05.09, 22:06
  2. Ints und bools Binär lesen/schreiben
    Von liggi im Forum C/C++
    Antworten: 0
    Letzter Beitrag: 04.10.08, 13:57
  3. Datei lesen/schreiben binär/hex
    Von Thomasio im Forum C/C++
    Antworten: 1
    Letzter Beitrag: 15.01.08, 19:03
  4. binär in datei schreiben
    Von zapp91 im Forum C/C++
    Antworten: 9
    Letzter Beitrag: 10.10.07, 16:03
  5. Antworten: 2
    Letzter Beitrag: 27.04.07, 08:16