Struct in Datei schreiben aus CodeGuru.com



  • OK, auf die Variante kam ich auch schon. Dann muss ich zur Länge 1 dazu rechnen, aber ich dachte es geht evtl doch noch eleganter (was hald bei dieser Version elegant ist 😃)


  • Mod

    beg_offl schrieb:

    Dann muss ich zur Länge 1 dazu rechnen

    Wieso?

    , aber ich dachte es geht evtl doch noch eleganter

    Du kannst gerne noch ein 10000 Zeilen Templatemonster davor schreiben, das es dir ermöglicht, alles und jeden Typen auf die gleiche einfache Art und Weise zu serialisieren. Ich schlage vor, das Resultat zu veröffentlichen, da viele Leute da dran interessiert wären. "Boost Serialization" wäre ein guter Name 🙂 .



  • Hab Momentan keine Zeit daran groß weiter zu machen, aber wenn dann werd ich´s hier reinstellen um mir meine "Watsche" abzuholen . 🙂 🙂

    Ähm, Sepp, wie schon mal geschrieben, ich bin noch nicht bei Templates, also werd ich selbst auch keines erstellen. Das ganze ist rein aus "hey ich hab ne Strukt mit nem String, schreib das mal auf einmal raus" geboren.



  • Das versteh ich nicht ganz, wie ich "dahin" kommen soll:

    char* pointerToData = "test"/* ... */;
    int dataLen = 4/* ... */;
    std::string data;
    data.append(pointerToData, dataLen);
    

    ich lese erst die länge mit

    datei >> len ; ein.

    so, wie krieg ich jett nen char Pointer wie in dem obrigen Beispiel? (Das Rausschreiben hab ich jetzt ums ' ' ergänzt.

    Sorry, Leute, für euch ist das bestimmt kinderkacke, aber ich hab momentan nicht soviel Zeit mich länger damit zu beschäftigen. Und ich bin hald noch nicht soo weit mit c++



  • gar keiner?



  • Und hat evtl. noch jmd. einen Tip für ne einigermaßen gute OFFLINE Referenz?


  • Mod

    beginner_offl schrieb:

    Und hat evtl. noch jmd. einen Tip für ne einigermaßen gute OFFLINE Referenz?

    cppreference bietet ein Offline-Archiv an.



  • beg_offl schrieb:

    stream >> data => das geht dann aber nur wenn in der Datei nur Text steht , bzw. ich alles alles in den String data einlesen will, hab ich das jetzt richtig verstanden?

    Nein. Du kannst in C++ auch binär schreiben und lesen.

    beginner_offl schrieb:

    so, wie krieg ich jett nen char Pointer wie in dem obrigen Beispiel? (Das Rausschreiben hab ich jetzt ums ' ' ergänzt.

    Warum nicht einfach binär ?

    #include <string>
    #include <fstream>
    #include <vector>
    
    void writeString(std::fstream &file, std::string &str)
    {
    	file << (int)str.length();
    	file << str;
    }
    
    std::string readString(std::fstream &file)
    {
    	int len;
    	file >> len;
    	std::vector<char> buffer(len);
    	file.read(&buffer[0], len);
    	return std::string(buffer.begin(), buffer.end());
    }
    
    void testWrite()
    {
    	std::fstream file("testce.txt", std::ios::binary|std::ios::out);
    
    	std::string s1 = "Hallo";
    	std::string s2 = "Welt";
    
    	writeString(file, s1),
    	writeString(file, s2);
    
    	file.close();
    }
    void testRead()
    {
    	std::fstream file("testce.txt", std::ios::binary|std::ios::in);
    
    	std::string s1 = readString(file);
    	std::string s2 = readString(file);
    
    	file.close();
    }
    int main()
    {
    	testWrite();
    	testRead();
    
    	return 0;
    }
    

    beginner_offl schrieb:

    Und hat evtl. noch jmd. einen Tip für ne einigermaßen gute OFFLINE Referenz?

    Dritter Treffer bei Google.


  • Mod

    @Darkshadow44:
    -Das geht schief, wenn der String mit einer Zahl beginnt -> Trennzeichen vergessen
    -Wozu der Cast nach int? Das Einzige, was du dadurch erreichst, ist doch, dass es für lange Strings nicht mehr funktioniert.
    -Lies doch direkt in den String! Wozu der vector? Strings sind garantiert am Stück gespeichert.



  • SeppJ schrieb:

    @Darkshadow44:
    -Das geht schief, wenn der String mit einer Zahl beginnt -> Trennzeichen vergessen
    -Wozu der Cast nach int? Das Einzige, was du dadurch erreichst, ist doch, dass es für lange Strings nicht mehr funktioniert.
    -Lies doch direkt in den String! Wozu der vector? Strings sind garantiert am Stück gespeichert.

    1. Oh, ich dachte die Operatoren "<<" und ">>" könnten auch zum schreiben von Binärdaten genutzt werden... 😮
      Korrektur ohne Rücksicht auf Endianess:
    //Read
    //file >> len;
    file.read((char*)&len, sizeof(len));
    
    //Write
    //file << (int)str.length();
    int len = str.length();
    file.write((char*)&len, sizeof(len));
    
    1. Ok ich sollte unsigned int verwenden, oder besser uint_32t. Die Maximale Länge eines strings ist auf 32Bit Systemen übrigends auch nur 4 Bytes.
      "std::string::size_type" würde ich nicht werwenden (sogar davon abraten), da die Länge auf 32Bit Systemen 4 Bytes ist, auf 64Bit Systemen aber 8 Bytes.
      Was spricht dagegen es immer auf 32Bit zu limitieren, und sich dafür 32Bit und 64Bit Versionen der Programme gleich verhalten ?
    2. Sicher dass strings auch vor C++11 garantiert am Stück sind ? Laut diesem Stackoverflow Post ist das in C++03 noch nicht garantiert, nur wahrscheinlich.
      C++11 Variante:
    //std::vector<char> buffer(len);
    //file.read(&buffer[0], len);
    //return std::string(buffer.begin(), buffer.end());
    data.resize(len);
    file.read(&data[0], len);
    return data;
    

  • Mod

    nur wahrscheinlich.

    Die vage Definition des Standards ist hier unwichtig. Ich kann dir (ohne nachzusehen) garantieren dass jede gängige existierende Implementierung die auch nur halbwegs relevant sein könnte string so speichert. Zu viel language-lawyerei ist auch nicht gut, besonders wenn man dann - nur um der Theorie zu entsprechen - derartige Performance-Defizite zulässt.



  • @DarkShadow44

    Wahh.. Danke, ich hab die Referenz zu read falsch verstanden. Der Char Pointer ist wo es ingeht, nicht von wo es kommt.
    => Ich dachte die ganze ZEit ich brauche einen CharPointer der auf das erste Zeichen des Strings IN MEINER DATEI zeigt. <=

    F..k, dann ist mir das Beispiel auch klar. Denke so werd ich es dann auch lösen.
    Ich muss echt daran arbeiten, die REfernz besser anzusehen usw.


  • Mod

    Im Jahr 2014 setze ich C++11 voraus. Selbst ohne C++11 ist der Einwand nicht praxisrelevant, die Verbesserung hingegen bringt locker mal 100% Performancegewinn.

    Zu 1 & 2: Schreib die Zahl doch einfach im Klartext! Was soll das Gehacke, mit dem du alles nur unportabel machst?



  • SeppJ schrieb:

    Im Jahr 2014 setze ich C++11 voraus. Selbst ohne C++11 ist der Einwand nicht praxisrelevant, die Verbesserung hingegen bringt locker mal 100% Performancegewinn.

    Ich habe lediglich versucht komplett Standardkonform zu sein.

    SeppJ schrieb:

    Zu 1 & 2: Schreib die Zahl doch einfach im Klartext! Was soll das Gehacke, mit dem du alles nur unportabel machst?

    Wir waren am Anfang bei Binärdateien, insofern bin ich dabei geblieben. Die Endiandess kann man ja noch berücksichtigen.
    Und wenn die streams keine besseren Methoden bieten muss man halt die nutzen die es gibt. 🙂


  • Mod

    DarkShadow44 schrieb:

    SeppJ schrieb:

    Im Jahr 2014 setze ich C++11 voraus. Selbst ohne C++11 ist der Einwand nicht praxisrelevant, die Verbesserung hingegen bringt locker mal 100% Performancegewinn.

    Ich habe lediglich versucht komplett Standardkonform zu sein.

    Selbst dann kannst du direkt den String initialisieren, mittels istreambuf_iterator, ohne Umweg.

    SeppJ schrieb:

    Zu 1 & 2: Schreib die Zahl doch einfach im Klartext! Was soll das Gehacke, mit dem du alles nur unportabel machst?

    Wir waren am Anfang bei Binärdateien, insofern bin ich dabei geblieben. Die Endiandess kann man ja noch berücksichtigen.
    Und wenn die streams keine besseren Methoden bieten muss man halt die nutzen die es gibt. 🙂

    Die kanonische Methode der binären Speicherung eines Strings ist eben: Länge, Trennzeichen, Inhalt. Niemand hat verlangt, die Länge auch binär zu speichern. Das hat doch nur Nachteile!


  • Mod

    Das hat doch nur Nachteile!

    Das ist offenbar falsch. Mit der Annahme dass die Endianness der Maschinen mit denen gelesen bzw. geschrieben wird gleich ist, wird das Schreiben und Parsen laufzeit-effizienter sein (da branch-free) und bei etwas größeren Längen auch weniger Zeichen in die Datei schreiben (im Bezug auf das Datum in welches serialisiert wird). Falls das Kriterien sind gibt es auch Vorteile.
    🤡

    Selbst dann kannst du direkt den String initialisieren, mittels istreambuf_iterator, ohne Umweg.

    Nein, auf gar keinen Fall. Das ist lahmer als Christopher Reeves Beine. Auf manchen Maschinen um Faktor 40.



  • char* pointerToData = "test"/* ... */; 
    int dataLen = 4/* ... */; 
    std::string data; 
    data.append(pointerToData, dataLen);
    

    Die frage bleibt, wo kommt der Zeiger auf char her, wenn ich nur die Länge aus der Datei mit >>len ,gelesen habe.
    Das ist ja was anderes wie read. ??

    Kann das bitte mal jmd erklären?


  • Mod

    Arcoth schrieb:

    Selbst dann kannst du direkt den String initialisieren, mittels istreambuf_iterator, ohne Umweg.

    Nein, auf gar keinen Fall. Das ist lahmer als Christopher Reeves Beine. Auf manchen Maschinen um Faktor 40.

    Sicher? Ich habe momentan keine Lust, das zu messen, aber ich meine mich zu erinnern, dass genau diese Frage schon mal kam und der istreambuf_iterator sehr gut aussah gegenüber read. Und ganz gewiss gegenüber read + vector-Indirektion.


  • Mod

    SeppJ schrieb:

    Sicher?

    http://insanecoding.blogspot.co.uk/2011/11/how-to-read-in-file-in-c.html

    Die Kommentare.

    C/C++: 7.5
    [..]
    iter: 110

    C: 18.3
    C++: 21
    [...]
    iter: 209.3

    Gut, also etwa Faktor 10-15. Bei einigen guten Implementierungen ein kleineres Verhältnis da std::copy wohl für POD-Typen memcpy anwendet sodass mit der ganzen Registerbreite kopiert wird. Irgendwie sowas.


  • Mod

    Arcoth schrieb:

    SeppJ schrieb:

    Sicher?

    http://insanecoding.blogspot.co.uk/2011/11/how-to-read-in-file-in-c.html

    Die Kommentare.

    C/C++: 7.5
    [..]
    iter: 110

    C: 18.3
    C++: 21
    [...]
    iter: 209.3

    Gut, also etwa Faktor 10-15. Bei einigen guten Implementierungen ein kleineres Verhältnis da std::copy wohl für POD-Typen memcpy anwendet sodass mit der ganzen Registerbreite kopiert wird. Irgendwie sowas.

    Irgendwelche ausgewählten Kommentare zu irgendeinem Blog als Quelle? Wer weiß, wer da was wie gemessen hat? Und die Kommentare, die nicht so extrem sind, unterschlägst du auch noch? Bei einem der zitierten steht VS 2005 als Compiler, nicht gerade moderner Standard. Beim Originalblog ist der Faktor 2-2.5, das ist schon normaler.


Anmelden zum Antworten