Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

29.01.2012, 19:56

Verständnisproblem fstreams im binary Mode

Hallo, ich hab ein Verständnis Problem bezüglich den fstreams (va was ifstream anbelangt)

Ich habe eine Struktur, die ich im binary Modus in eine Datei schreibe.
Hier mal die Struktur, um die es geht:

C-/C++-Quelltext

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
struct STileConfig_Textures
{
    STileConfig_Textures() : texture_ID(0) {};
    STileConfig_Textures(const unsigned int texture_ID) : texture_ID(texture_ID) {};
    
    unsigned int texture_ID; //ID der Textur
    unsigned int map_Tile; //Tile in der Map, an der sich die Textur befindet
    
    //Operator zur Ausgabe per Streams
    friend std::ostream & operator << (std::ostream & out, STileConfig_Textures const & data) 
    { 
        //Der Reihe nach die einzelnen Konfigurationsteile in den Stream schrieben
        out << endl;
        out.write((char*) &data.texture_ID, sizeof(data.texture_ID)); //Textur Information schreiben
        out.write((char*) &data.map_Tile, sizeof(data.map_Tile)); //Map Tile schreiben

        out.flush(); //Bisher geschriebene Daten im Puffer in den Ausgangskanal schreiben
        
        return (out); //Den Stream zurückliefern
    }

    //Operator zur Eingabe per Streams
    friend std::istream & operator >> (std::istream & in, STileConfig_Textures & data) 
    { 
        in.ignore(); //Löscht den eingabebuffer, damit keine falschen zeichen eingelesen werden
        
        in.read((char*) &data.texture_ID, sizeof(data.texture_ID)); //Textur Information lesen
        in.read((char*) &data.map_Tile, sizeof(data.map_Tile)); //Map Tile lesen

        return in;
    }
};


Nun habe ich mehrere Instanzen dieser Struktur in einem Vector gespeichert, und dann mit Hilfe der Funktion copy den Inhalt der Struktur in eine Datei geschrieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
   vecor<STileConfig_Textures> vTextureConfig; //In dem Vecor sind Daten drinnen, der Vector ist nicht leer!
    //Alle Elemente der Texturen Speichern
    output.open("Data/Test.txt", ios::binary);
    if(output == NULL)
        return false;

    copy(m_vTextureConfig.begin(), m_vTextureConfig.end(),std::ostream_iterator<STileConfig_Textures>(output)); //Schreibt alle Elemente der Karte in die Datei
    output.close(); //Schreibzugriff beenden


Das einlesen über die copy Funktion funktioniert auch super.
Ich verstehe nur nicht, wieso ich die Datei jetzt nicht einfach direkt in eine Struktur einlesen kann, die nicht in einem Vektor ist (also nicht über die copy funktion).

C-/C++-Quelltext

1
2
3
4
5
6
7
    STileConfig_Textures tile;
    ifstream input("Data/Test.txt", ios::binary);
    if(input == NULL)
        return false;

    input.read((char*) &tile.texture_ID, sizeof(tile.texture_ID)); //Textur Information lesen
    input.read((char*) &tile.map_Tile, sizeof(tile.map_Tile)); //Map Tile lesen


Bei dem versuch bekomme ich nämlich keine richtigen Werte zurück :|
Ich habe mit dem Debugger überprüft, ob die Werte stimmen, wenn ich meine Daten mit der copy Funktion wieder einlese. Das funktioniert problemlos.

Ich hoffe, ich hab mich verständlich ausdrücken können und ihr könnt mir helfen :)

Schönen Abend noch und liebe Grüße,
Ombalat

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

29.01.2012, 20:09

Stichwort: Struct Padding ;)

3

31.01.2012, 17:46

Hallo nochmal,
ich hatte leider die letzten 2 Tage nicht so viel Zeit, deswegen melde ich mich erst jz wieder ...

Ich habe festgestellt, dass ich das in.ignore vergessen hab, dass ich beim überladenen operator (der in der Copy funktion aufgerufen wird), verwendet habe.
Mit Hilfe von dem kann ich dann die Struktur problemlos wieder einlesen.

Was das aber mit Struct Padding zu tun hat verstehe ich nicht so ganz?
Mit in.ignore lösche ich doch den eingabepuffer, um somit fehlerhafte ergebnisse am Anfang zu verhindern, soweit ich das verstanden habe.
Bei Struct Padding geht es doch darum, dass man nicht genau weiß, wie groß eine Struktur ist.
Ich verwende aber für jede Struktur doch die selbe Grüße, weil ich immer unsigned int Variablen habe, die ich auch wieder einlese.
Die werden doch immer mit 4 Bit aus - und eingelesen (Über die sizeof() bekommt man doch diese Größe)?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

31.01.2012, 18:06

Wieso solltest Du "ignore" benutzen? Damit löschst Du den Eingabepuffer, aber wieso glaubst Du, dass es "fehlerhafte Ergebnisse am Anfang" gibt oder Du sie damit überspringen kannst?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

31.01.2012, 18:38

Ich hab das mal irgendwo gelesen, dass es vorkommen kann, wenn man eine Datei mit einem fstream öffnet, dass im Eingabepuffer schon etwas drinnen steht
(von einer vorherigen Verwendung, bevor dieser erzeugt wurde oder iwie so war das, weiß es aber um ehlich zu sein nicht mehr so genau).
Mit ignore löscht man diesen deswegen, damit man eben nur die Werte (aus der Datei) bekommt, die drinnen stehen.
Bei mir hat das bis jetzt immer funktioniert so, deswegen meine frage bezüglich struct padding, was mit dem eingabepuffer ja nciht viel zu tun hat ;)

Edit:
Bzw hab ich das auch geglaubt, weil ich bis jetzt IMMER fehlerhafte einlesungen am Anfang hatte, wenn ich mit fstreams gearbeitet habe
(auch mit den stream - operator "<<" und keiner binär - Datei. Also wenn ich normalen Text ausgelesen habe)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

31.01.2012, 19:39

Öhm... Also ich will nicht von mir behaupten die C++ Spec gefressen zu haben, aber wenn ich einen Stream öffne und dafür sogar einen Konstruktor aufrufe, dann erwarte ich eigentlich nicht, dass da Müll drin steht und ich erstmal ignore() aufrufen muss, um damit arbeiten zu können.

Hast Du mal geschaut, ob "std::ios::in|std::ios::binary" einen Unterschied macht zu "binary" (bzw "std::ios::out|std::ios::binary")?
(sollte es laut Spec allerdings nicht)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »BlueCobold« (31.01.2012, 20:28)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

31.01.2012, 20:22

Also ich wüsste nicht was du da mit ignore() anfangen willst?
ignore() löscht nicht den Eingabepuffer, sondern wirft (wie der Name schon sagt) ein Byte weg.
Sowas wie "fehlerhafte Ergebnisse am Anfang" gibt es nicht.

Auf das struct padding bin ich gekommen weil es ja offenbar funktioniert wenn du die Member einzeln schreibst. Aber das ist in der Tat hier nicht das Problem.
Ich denke das Problem ist dass du stream iteratoren verwendest, die formatted I/O betreiben. Und das ist nicht was du willst...

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (31.01.2012, 20:31)


8

01.02.2012, 10:45

Wenn ich dich richtig verstanden hab, meinst du, ich soll die copy funktion weglassen, und somit auch keine stream iteratoren verwenden?

Also statt der copy einfach so was in der art?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
//Zum schreiben
for(vector<STileConfig_Textures>::iterator iter = m_vTextureConfig.begin(); iter != m_vTextureConfig.end(); iter++)
     ofstream << iter;

//Zum lesen
while(!input.eof())
{
     STileConfig_Textures tempTile;
     ifstream >> tempTile;
     vTextureConfig.pushback(m_vTextureConfig);
}


o/ifstream sind hier nur platzhallter für die eigendlichen Files dann. Das der Code so nicht funktionsfähig ist, ist mir klar.
Ich wollte nur mal fragen, ob ich dich prinzipiell verstanden habe :)
Da ich den Operator "<<" und ">>" überladen habe sollte es so doch eigendlich funktionieren?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

01.02.2012, 12:17

Ah ok, wenn du den << operator richtig überladen hast, dann sollte es funktionieren, ja.
Das Problem ist, dass "richtig" in dem Fall bedeutet, dass der operator << binär in die Datei schreibt, was eigentlich gegen die Konvention ist.
Ich würds lieber mit ner serialize() Funktion/Methode machen...

10

01.02.2012, 13:14

Ja, das habe ich mir eh schon gedacht, dass ich das ändern werde und über eine Funktion ohne den ">>" operatoren machen werde ;)
Die überladung war im ertsen post schon u sehen, nur müsste man sich jetzt natürlich nur das ignore wegdenken dort :D

Werbeanzeige