mit memcpy und fstream in Datei schreiben



  • Hi,
    Ich möchte in eine Datei schreiben.
    das würde ich gerne gepuffert machen.

    char Buffer_ptr[FILE_BUFFER_SIZE];
    std::fstream swap_file_ptr("sdfsfd",ios....);
    std::streambuf *Buffer_ptr_streambuf;
    Buffer_ptr_streambuf=swap_file_ptr.rdbuf()->pubsetbuf(Buffer_ptr,FILE_BUFFER_SIZE);
    

    Ich kann jetzt über den pointer Buffer_ptr_streambuf in Buffer_ptr schreiben mit

    Buffer_ptr_streambuf->sputn("..........",sizeof("........."));
    

    Wenn ich nun den Buffer_ptr in die Datei schreiben will so muß ich

    Buffer_ptr_streambuf->pubsync();
    

    Das funktioniert so, daß die Funktion sputn den
    streambuf::epptr
    pointer auf das zuletzt geschriebene Byte int Buffer_ptr setzt. So habe ich das zumindest verstanden.
    Das
    streambuf::pubsync()
    Schreibt dann vom startpunkt bis zum streambuf::epptr.

    --------------------------------------------------------------------
    Kann ich irgendwie den epptr pointer selber setzen????
    Ziel ist es folgendes machen zu können:

    //In das Buffer Array schreiben
    memcpy(Buffer_ptr,"........",sizeof("..........."));
    //std::streambuf sagen daß zeichen im buffer sind
    ?????????????????????;
    //Die Zeichen in die Datei schreiben
    Buffer_ptr_streambuf->pubsync();
    

    Also wie bekomme ich das
    ?????????????????;
    hin ??
    ---------------------------------------------------------------------
    Ableiten weiß ich nicht wie, da die
    std::streambuf
    Instanz von
    std::fstream
    erzeugt wurde.

    Gruß


  • Mod

    Das hier klingt nach dem, was du suchst:

    http://www.cplusplus.com/reference/iostream/streambuf/setp/

    Frage: Dir ist aber schon klar, dass die Standardein-/ausgabe bereits gepuffert ist? Wenn du durch deine memcpy Operation nicht irgendeine neue tolle Funktionalität bekommst, ist dein Programm - zumindest geschwindigkeitstechnisch - kein Fortschritt.

    Finde ich aber trotzdem mal interessant zu sehen, wie man die Streamoperatoren selbst implementiert.



  • /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4/streambuf

    528       /**
    529        *  @brief  Setting the three write area pointers.
    530        *  @param  pbeg  A pointer.
    531        *  @param  pend  A pointer.
    532        *  @post  @a pbeg == @c pbase(), @a pbeg == @c pptr(), and
    533        *         @a pend == @c epptr()
    534       */
    535       void
    536       setp(char_type* __pbeg, char_type* __pend)
    537       {
    538         _M_out_beg = _M_out_cur = __pbeg;
    539         _M_out_end = __pend;
    540       }
    
    515       char_type*
    516       epptr() const { return _M_out_end; }
    

    Mir genügt das ende. Die funktion war nicht das Problem. Beide Member sind protected. Ich habe keinen zugriff.
    Ich versuche nun:

    class my_streambuf : public std::streambuf
    {
       public:
            char* my_epptr() const { return std::streambuf::epptr(); }
    };
    

    Dann einen Pointer vom Type
    my_streambuf
    Und dann zugreifen.
    Hoffe das klappt.

    Wegen der Standartpufferung:
    Das wird eine Rescue funktion die auf die Festpalatte schreibt, wenn kein Arbeitsspeicher im System mehr verfügbar ist.
    + Sie muß schnell gehen.
    Deswegen eigene Pufferung.

    gtuß



  • Hi SepJ,
    Hab ganz übersehen, daß mir epptr ja nur den pointer gibt, ich ihn aber nicht setzen kann. Du hast Recht mit deiner Funktione. Danke nochmal.

    Das ganze läuft jetzt.
    Die Lösung:

    class my_streambuf : public std::streambuf
    {
       public:
            char* my_epptr() const { return std::streambuf::epptr(); }
            void my_setp(char *start,char *end){ setp(start,end);}
    };
    
    char Buffer_ptr[FILE_BUFFER_SIZE];
    std::fstream swap_file_ptr("sdfsfd",ios....);
    std::my_streambuf *Buffer_ptr_streambuf;
    Buffer_ptr_streambuf=reinterpret_cast<my_streambuf *>swap_file_ptr.rdbuf()->pubsetbuf(Buffer_ptr,FILE_BUFFER_SIZE);
    

    Dann kann man mit

    //In das Buffer Array schreiben
    memcpy(Buffer_ptr,"........",sizeof("..........."));
    //std::streambuf sagen daß zeichen im buffer sind
    Buffer_ptr_streambuf->my_setp(Buffer_ptr,(Buffer_ptr+tmpp.size()));
    //Die Zeichen in die Datei schreiben
    Buffer_ptr_streambuf->pubsync();
    

    In die Datei schreiben.
    Frag mich ob ich die Pointer wieder zurücksetzen muß, um die alte Funktionalität der Klasse zu behalten.

    Gruß


  • Mod

    AlexXXx schrieb:

    /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4/streambuf

    528       /**
    529        *  @brief  Setting the three write area pointers.
    530        *  @param  pbeg  A pointer.
    531        *  @param  pend  A pointer.
    532        *  @post  @a pbeg == @c pbase(), @a pbeg == @c pptr(), and
    533        *         @a pend == @c epptr()
    534       */
    535       void
    536       setp(char_type* __pbeg, char_type* __pend)
    537       {
    538         _M_out_beg = _M_out_cur = __pbeg;
    539         _M_out_end = __pend;
    540       }
    
    515       char_type*
    516       epptr() const { return _M_out_end; }
    

    Mir genügt das ende. Die funktion war nicht das Problem. Beide Member sind protected. Ich habe keinen zugriff.

    Häh? Die Funktion setp macht doch EXAKT das was du willst, sowohl laut Standardreferenz als auch im Quellcode, wie du gesehen hast.

    edit: Ok, da hast du es selbst schneller gemerkt, als ich geantwortet habe.

    Wegen der Standartpufferung:
    Das wird eine Rescue funktion die auf die Festpalatte schreibt, wenn kein Arbeitsspeicher im System mehr verfügbar ist.
    + Sie muß schnell gehen.
    Deswegen eigene Pufferung.

    gtuß

    Das kann ich mal überhaupt nicht nachvollziehen: Der Speicher ist voll und du legst noch zusätzlich deinen eigenen Ausgabepuffer an der Speicher braucht und das alles, obwohl es bereits eine gepufferte Ausgabe gibt?

    Um im Notfall etwas zu retten will man eher eine ungepufferte Ausgabe (wie cerr), damit überhaupt noch irgendwas auf der Platte ankommt.



  • Nein der Speicher zum auslagern ist fest und wird im konstruktor erzeugt.
    Das Problem waren nicht die Funktionen. Das muß man ja nur nachlesen.
    Lediglich daß eben jene, welche ich benötigte protected sind.
    Siehe:
    http://www.cplusplus.com/reference/iostream/streambuf/
    Ich habe im ersten text schon geschrieben, daß ich nicht weiß wie ich ableiten muß. Hatte aber schnell die Lösung.
    Man kann den Zugriffsschutz umgehen, in dem man eine Klasse von
    streambuf ableitet, und dann öffentlich funktionen deklariert, welche dann die benötigten Funktionen aufrufen.

    Die erste lösung ist falsch. Es wird noch folgendes benötigt:

    class my_streambuf : public std::streambuf
    {
       public:
            char* my_epptr() const { return std::streambuf::epptr(); }
            void my_setp(char *start,char *end){ setp(start,end);}
            //erhöht den put zähler um n
            void my_pbump(int n){pbump(n);}
    
    };
    
    char Buffer_ptr[FILE_BUFFER_SIZE];
    std::fstream swap_file_ptr("sdfsfd",ios....);
    std::my_streambuf *Buffer_ptr_streambuf;
    Buffer_ptr_streambuf=reinterpret_cast<my_streambuf *>swap_file_ptr.rdbuf()->pubsetbuf(Buffer_ptr,FILE_BUFFER_SIZE);
    

    Schreiben mit:

    //In das Buffer Array schreiben
    memcpy(Buffer_ptr,"........",sizeof("..........."));
    //std::streambuf sagen daß zeichen im buffer sind
    Buffer_ptr_streambuf->my_setp(Buffer_ptr,(Buffer_ptr+tmpp.size()));
    //Den put zähler erhöhen
    Buffer_ptr_streambuf->my_pbump(tmpp.size());
    //Die Zeichen in die Datei schreiben
    Buffer_ptr_streambuf->pubsync();
    

    Schreiben mit nur dem put zähler erhöhen schlägt genau so fehl wie schreiben mit
    Grenzen nicht setzen.

    Gruß



  • 🙂
    Wenn ich fertig bin, werde ich auf die Festplatte schreiben können, ohne weiteren Speicher zu benötigen. Und jener Speicher den ich habe, wird nicht mehr freigegeben, bis die Instanz der klasse vom Speicher genommen wird.

    Kurtz: Ist genügend Speicher vorhanden, um die Klasse zu instanzieren, kann sie ausschließlich auf der Festplatte arbeiten. Damit das System nicht ganz in die knie geht benötige ich einen puffer, dessen Größe konstant sein muß und im konstruktor alloziirt wird.

    Wenn ich die arbeit hier nicht mache, ist ja klar dass nichts mehr auf der Festplatte ankommt.
    Deswegen.

    Rescue
    +geschwindigkeit
    ->eigener puffer

    Genau das ist ja der Sinn des ganzen.



  • Im übrigen macht das normalerweise das betriebssystem von selbst, das ist aber irrsinnig langsam.
    new(nothrow)
    Man muß was tuen damit ne ausnahme geworfen wird. Zumindest bei meinem kompiler.

    gruß



  • AlexXXx schrieb:

    new(nothrow)
    Man muß was tuen damit ne ausnahme geworfen wird. Zumindest bei meinem kompiler.

    was willst du damit sagen? Oo

    bb



  • 🙂


Anmelden zum Antworten