stream kopieren



  • Du könntest es dir mit std::copy und den entsprechenden Stream-Iteratoren recht schnell machen lassen. Siehe http://www.cplusplus.com/reference
    Oder du machst es dir noch einfacher und benutzt boost::iostreams::copy:

    #include <boost/iostreams/copy.hpp>
    
    /* ... */
    http_istream_type httpIstream;
    std::ofstream outFileStream("outfile.txt");
    std::streamsize charsWritten =  boost::iostreams::copy(httpIstream, outFileStream); //fertig :)
    

    /edit: oder noch komplizierter... wieso komm ich nie auf die einfachen Methoden? *kopf->tisch*



  • hola

    @SeppJ

    das hatte ich auch noch im kopf. aber der codeguard von CodeGear C++ Builder meldet mir:

    Fehler 00114. 0x310000 (Thread 0x0EF4):
    Falscher Parameter: Falsches Datei- oder Pipe-Stream (0x329DF840) wurde an die
     Funktion weitergegeben.
    fputc(0xFFFFFFFF ['ÿ'], 0x329DF840) 
    
    | c:\program files\codegear\rad studio\6.0\include\../include/dinkumware/fstream Zeile 55:
    | template<> inline bool _Fputc(char _Byte, _Filet *_File)
    | 	{	// put a char element to a C stream
    |>	return (fputc(_Byte, _File) != EOF);
    | 	}
    | 
    Aufrufhierarchie:
       0x0041E2B1(=webcontrol.exe:0x01:01D2B1) c:\program files\codegear\rad studio\6.0\include\../include/dinkumware/fstream#55
       0x0041CF9E(=webcontrol.exe:0x01:01BF9E) c:\program files\codegear\rad studio\6.0\include\../include/dinkumware/fstream#246
       0x004036C3(=webcontrol.exe:0x01:0026C3) c:\program files\codegear\rad studio\6.0\include\../include/dinkumware/streambuf#144
       0x0041BCE0(=webcontrol.exe:0x01:01ACE0) c:\program files\codegear\rad studio\6.0\include\../include/dinkumware/streambuf#707
       0x0041B615(=webcontrol.exe:0x01:01A615) c:\program files\codegear\rad studio\6.0\include\dinkumware\xutility#1515
       0x0041AEB2(=webcontrol.exe:0x01:019EB2) c:\program files\codegear\rad studio\6.0\include\dinkumware\xutility#1540
    

    @Ad aCTa
    geht auch nicht:

    [BCC32 Fehler] FormMain.cpp(113): E2227 Zu viele Parameter im Aufruf von fstream::rdbuf() const
    

    @Pumuckl
    aus gruenden die ich jetzt nicht eroertern will, kann ich boost hier nicht verwenden.

    bleibt mir vielleicht nichts uebrig ausser das ich mir da selber eine copy-routine stricke

    Meep Meep



  • ups ...

    hab da euch eine kleine unwahrheit unterbreitet. der http-stream ist nicht von einem ostream abgeleitet sondern von

    std::basic_iostream<char>
    

    Meep Meep



  • hola nochmal

    also das problem von codeguard kommt auch bei diesem codefetzen:

    std::ostream& operator<<(std::ostream &out, tcpstream &stream)
    {
       const int buffer_size = 0x1000;
       char *buffer = new char[buffer_size];
    
       int temp;
    
       while(!stream.read(buffer, buffer_size).eof())
       {
          out.write(buffer, buffer_size); // (1)
       }
    
       out.write(buffer, stream.gcount());
    
       return out;
    }
    

    bei (1)

    kann es sein, das der codeguard da bei etwas meckert was garnicht stimmt ?
    wenn ich codeguard abschalte funktioniert es einwandfrei.
    aber ich will das nicht so lassen, falls es nur 'zufaellig' funktioniert.

    meep meep

    PS: @SeppJ
    nun funktioniert es auch mit ofstream << stream.rdbuf();



  • > [BCC32 Fehler] FormMain.cpp(113): E2227 Zu viele Parameter im Aufruf von fstream::rdbuf() const

    Das const stinkt mir. rdbuf() akzeptiert einen o. keinen Parameter. Immer.



  • pumuckl schrieb:

    /edit: oder noch komplizierter... wieso komm ich nie auf die einfachen Methoden? *kopf->tisch*

    std::string Antwort("C++") ;



  • also das mit

    ofstream << stream.rdbuf();
    

    funktioniert zwar, aber es wird in der datei nur ein bruchteil gespeichert was wirklich kommen muesste.
    ich probiere eine datei mit rund 700kb zu laden, abgespeichert werden aber nur 1013 bytes.

    hab nun folgenden source zum kopieren des streaminhaltes verwendet:

    /* mein http-stream erbt von tcpstream */
    std::ostream& operator<<(std::ostream &out, tcpstream &stream)
    {
       const int buffer_size = 0x4000;
       char *buffer = new char[buffer_size];
    
       int temp;
    
       while(!stream.read(buffer, buffer_size).eof())
       {
          out.write(buffer, buffer_size); // (1)
       }
    
       out.write(buffer, stream.gcount());
    
       return out;
    }
    

    in der virtuellen function xsgetn von streambuf wird scheinbar nur der aktuell empfangene datensalat von meinem http-stream kopiert und dann wird der http-stream auf eof gesetzt. ist das so normal ? oder muss ich xsgetn auch noch mal ueberladen, damit das richtig funktioniert.
    xsgetn ruft nach dem die daten vom buffer des http-streams kopiert worden sind uflow() auf. hier werden auch wieder daten empfangen. diese werden jedoch nicht mehr kopiert, weil stream schon den status eof hat.

    Meep Meep



  • Meep Meep schrieb:

    also das mit

    ofstream << stream.rdbuf();
    

    funktioniert zwar, aber es wird in der datei nur ein bruchteil gespeichert was wirklich kommen muesste.

    Hast du die Fehlerflags des Streams abgefragt?



  • hi nexus

    ja beide stehen auf good

    Meep Meep



  • Meep Meep schrieb:

    ups ...

    hab da euch eine kleine unwahrheit unterbreitet. der http-stream ist nicht von einem ostream abgeleitet sondern von

    std::basic_iostream<char>
    

    und basic_iostream ist abgeleitet von basic_istream (und basic_ostream), und basic_istream<char> ist istream.

    versuch mal folgendes:

    std::copy (istream_iterator<char>(http_stream), istream_iterator<char>, ostream_iterator<char>(out_file_stream));
    


  • hola

    das problem hat sich in zwischen noch nicht loesen lassen.

    fuer das copieren nehme ich noch immer folgenden code:

    std::ostream& operator<<(std::ostream &out, tcpstream &stream)
    {
       const int buffer_size = 0x1000;
       char *buffer = new char[buffer_size];
    
       while(!stream.read(buffer, buffer_size).eof())
       {
          out.write(buffer, stream.gcount());
       }
    
       out.write(buffer, stream.gcount());
    
       delete[] buffer;
    
       return out;
    }
    

    eine pdf datei mit ca. 370 kb wurde anstandslos heruntergeladen und in den ofstream kopiert.
    bei einem bild mit rund 320kb werden nur 1013 b kopiert. bei einem anderen bild mit ca. 78kb groesse werden 40432 byte kopiert.
    scheinbar bekommt xsgetn irgendwann mal von meiner underflow function ein EOF geliefert. habe in allen zeilen wo ein ein EOF geliefert werden kann einen break-point gesetzt. die points werden aber nie erreicht.
    hier mal meine underflow rountine:

    int streambuf::underflow(void)
    {
       int temp   = 0;
       int len = egptr() - gptr();
    
       if(recv_mode == rm_chunked)
       {
          if(recv_len == 0)
          {
             temp = tcp_client.read(read_buffer, BUFFER_SIZE);
    
             if(temp != SOCKET_ERROR && temp != 0)
             {
                setg(read_buffer, read_buffer, read_buffer + temp);
                char *test = gptr();
                test;
                read_chunk_size();
                test = gptr();
                if(recv_len == 0)
                {
                   setg(read_buffer, read_buffer, read_buffer);
                   return EOF;
                }
                else
                {
                   recv_len -= egptr() - gptr();
                }
             }
             else
             {
                setg(read_buffer, read_buffer, read_buffer);
                return EOF;
             }
          }
          else
          {
             temp = tcp_client.read(read_buffer, BUFFER_SIZE < recv_len ? BUFFER_SIZE : recv_len);
             if(temp != SOCKET_ERROR && temp != 0)
             {
                recv_len -= temp;
                setg(read_buffer, read_buffer, read_buffer + temp);
             }
             else
             {
                recv_len = 0;
                setg(read_buffer, read_buffer, read_buffer);
                return EOF;
             }
          }
       }
    
       else if(recv_mode == rm_size) /* (1) */
       {
          if(recv_len != 0)
             temp = tcp_client.read(read_buffer, BUFFER_SIZE < recv_len ? BUFFER_SIZE : recv_len);
    
          if(temp != SOCKET_ERROR && temp != 0)
          {
             recv_len -= temp;
             setg(read_buffer, read_buffer, read_buffer + temp);
          }
          else
          {
             setg(read_buffer, read_buffer, read_buffer);
             return EOF; /* (2) */
          }
       }
    
       else  /* if rm_close || rm_none */
       {
          temp = tcp_client.read(read_buffer, BUFFER_SIZE);
          if(temp != SOCKET_ERROR && temp != 0)
          {
             setg(read_buffer, read_buffer, read_buffer + temp);
          }
          else
          {
             setg(read_buffer, read_buffer, read_buffer);
             return EOF;
          }
       }
    
    	return read_buffer[0]; /* (3) */
    }
    

    das bild mit dem ich gerade teste wird mit 'Content-Length: 1299788' geliefert.
    er spring also in zeile (1). bei zeile (2) hab ich einen break-point gesetzt. wird nie erreicht. also muesste er theoretisch ueber die return anweisung (3) ein eof zurueckgeben. ansonsten wuerde es keinen sinn machen warum der stream ploetzlich auf EOF gesetzt ist.
    aber auch wenn im buffer[0] ein -1 stehen wuerde, waere es doch was anderes als wenn ich ein (int)(-1) zurueck geben wuerde oder ?

    Meep Meep



  • aber auch wenn im buffer[0] ein -1 stehen wuerde, waere es doch was anderes als wenn ich ein (int)(-1) zurueck geben wuerde oder ?

    hmm scheinbar nicht. ich hab die returnanweisung mal geaendert:

    return static_cast<unsigned char>(read_buffer[0]);
    

    und ploetzlich funktioniert es. auch mit

    datei << stream.rdbuf();
    

    scheinbar wird in der returnanweisung aus (char)(-1)[11111111] ein
    (int)(-1)[11111111 11111111 11111111 11111111]. damit -1 auch -1 bleibt.
    ich war eigendlich der meinung das er [00000000 00000000 00000000 11111111] zurueck geben wuerde. bloeder denkfehler

    Meep Meep


Anmelden zum Antworten