Teil eines streams kopieren



  • Hi,
    ich hab einen istream und möchte daraus einen Ausschnitt in einen ostream kopieren. Bislang mache ich das indem ich einen extra buffer erzeuge, dort die Daten per seekg und read reinlese und dann den buffer in den ostream schreibe.

    Ich dachte mir aber, das muss doch eleganter gehen. Gefunden habe ich die copy-function aus <algorithm>. Leider wird überall immer nur beschrieben wie man damit den ganzen stream kopiert:

    std::stringstream src( std::ios_base::binary );
      src.str("hello world");
      std::stringstream dest( std::ios_base::binary );
    
      std::copy( std::istream_iterator<char>(src),
                 std::istream_iterator<char>(),
                 std::ostream_iterator<char>(dest) );
    

    Wie stelle ich es an, dass nur ein Teil des streams kopiert wird? z.B. die zeichen 4-8? Geht das überhaupt mit copy?

    gruß,
    eXi



  • Das erste Argument von copy stellt den Anfang und das zweite das Ende des zu kopierenden Bereichs dar.
    std::istream_iterator<char>(src) ist der Anfang vom Stream und std::istream_iterator<char>() ist das Ende.
    Um die Zeichen 4-8 zu kopieren bräuchtest du ein Iterator auf das Zeichen 4 und einen hinter das Zeichen 8. Während das erste kein Problem ist, wird das zweite schon schwieriger. Hilfreicher wäre ein copy_n ((noch) nicht STL). Kannst du als einfache Schleife schreiben.

    #include <iostream>
    #include <iterator>
    #include <algorithm>
    
    int main()
    {
        using namespace std;   
        istream_iterator<char> in(cin);
        ostream_iterator<char> out(cout, "\t");
    
        advance(in, 3);
        for(int i = 0; i < 4; ++i)
            *out++ = *in++;
    
        std::cin.get();
        return 0;
    }
    

    oder

    namespace mylib
    {
    #if HAB_COPY_N
    using woisses::copy_n;
    #else
    template<class InputIter, class OutputIter>
    OutputIter copy_n(InputIter first, size_t n, OutputIter out)
    {
        for(; n > 0; --n)
            *out++ = *first++;
        return out;
    }
    #endif
    }
    
    int main()
    {
        using namespace std;   
        istream_iterator<char> in(cin);
        ostream_iterator<char> out(cout, "\t");
    
        advance(in, 3);
        mylib::copy_n(in, 4, out);
    
        std::cin.get();
        return 0;
    }
    


  • @brotbernd: danke für den code. Wie performant ist eine solche Lösung? werden die Zeichen da nicht alle einzeln kopiert?

    Vielleicht kurz was zum Hintergrund: ich brauche eine Funktion um Teilbereiche einer Binär-Datei in den Speicher oder in eine separate Datei zu kopieren. Diese Teilbereiche können relativ groß sein. Fahre ich da evtl. doch besser mit meiner alten Lösung? Also dass ich die Daten blockweise (16kB oder so) in einen Buffer lese und dann wegschreibe?



  • eXistence schrieb:

    Fahre ich da evtl. doch besser mit meiner alten Lösung? Also dass ich die Daten blockweise (16kB oder so) in einen Buffer lese und dann wegschreibe?

    Mit ziemlicher Sicherheit: Ja.


Log in to reply