2010-08-22 8 views
8

Wie lese ich genau 128 Bytes von einem fstream in ein String-Objekt?Wie kann ich genau 128 Bytes von einem fstream in ein String-Objekt lesen?

Ich schrieb einen Code, um die ersten 128 Bytes einer Datei zu lesen und sie und dann die letzten 128 Bytes der Datei zu drucken und das zu drucken. Der letzte Teil funktioniert, da Sie leicht zu EOF iterieren können, aber wie bekomme ich genau 128 Bytes von vorne? Der folgende Code funktioniert nicht, da Sie einem ifstream-Iterator keine 128 hinzufügen können, er ist nicht indexierbar, nur inkrementierbar (wie es scheint).

Sicher könnte ich einen Iterator machen und * ++ es 128 Mal, aber es muss eine einzige Linie direkten Weg, um es zu tun, richtig?

#include <iostream> 
#include <fstream> 
#include <string> 

int main(int argc, char **argv) 
{ 
    std::ifstream ifs ("input.txt",std::ifstream::in | std::ifstream::binary); 

    if (ifs.good()) 
    { 
    // read first 128 bytes into a string 
     ifs.seekg(0,std::ifstream::beg); 
     std::string first128((std::istreambuf_iterator<char>(ifs)), 
          (std::istreambuf_iterator<char>(ifs))+128); 

     std::cout << first128 << std::endl; 

    // read last 128 bytes into a string 
     ifs.seekg(-128,std::ifstream::end); 
     std::string last128((std::istreambuf_iterator<char>(ifs)), 
          std::istreambuf_iterator<char>()); 

     std::cout << last128 << std::endl; 

     return 0; 
    } 

    return 1; 
} 
+0

Wie wäre es mit istream :: readsome? – Chubsdad

+0

read/readsome arbeiten nur mit char * s und Sie können kein char * (nur ein const char *) von einem String-Typ bekommen, so dass Sie nicht direkt in einen String-Typ hineinlesen können. –

Antwort

1
char buffer[129]; 
ifs.read (buffer,128); 
buffer[128] = '\0'; 
first128 = buffer; 

Wie sei dies dann:

template <typename Itr, typename Out> 
void copy_n(Itr it, size_t count, Out out) 
{ 
    for(size_t i=0;i<count;++i) 
     out = *it++; 
} 

... 

std::string first128; 
std::istreambuf_iterator<char> it(ifs); 
copy_n(it, 128, 
    std::back_inserter<std::string>(first128)); 
+0

Byte Waster! Zeichenpuffer [128]; ifs.read (Puffer, 128); std :: string first128 (Puffer, 128); Aber wirklich möchte ich es so rein wie möglich machen. Antworten ohne spitze Klammern müssen nicht angewendet werden! –

+0

@ Southern Hospitality: Ich habe bearbeitet, um eine andere Version aufzunehmen. – ngoozeff

+0

Ich denke, die erste Antwort ist perfekt. Sie möchten in eine Zeichenfolge wechseln, erstellen Sie einfach eine Std :: string der Größe 128 und übergeben Sie diese als Puffer zum Lesen. Das Denken, das nicht rein ist, besagt, dass die Standardbibliothek irgendwie unrein ist. –

0

Meine Antwort verwendet einen Zwischenpuffer, aber vielleicht werden Sie froh sein, dass es Iteratoren verwenden die Zeichenfolge aus dem Puffer zu initialisieren.

std::vector<char> buffer(128); // create a buffer 
ifs.read(&buffer[0], buffer.size()); // read to buffer 
std::string first128(buffer.begin(), buffer.end()); // copy from vector 

Für mich scheint es, wie sie ein wenig zu süß mit der Umsetzung von iostreams bekam. Der Versuch, Iteratoren für Stream-I/O zu verwenden, ist übermäßig kompliziert.

Übrigens vermute ich, dass die Implementierung, die Sie versuchten, unter der Decke eine Vielzahl von Zwischenpufferung (vielleicht einige im Kernel, einige in der Bibliothek) sowie die Neuzuweisung und das Kopieren der Zeichenfolge mehrmals wie es wächst.

Eine andere Idee: Brauchen Sie das Ergebnis wirklich in einem Standardstring? Sie können einfach mit dem Vektor arbeiten - vermeiden Sie den letzten Schritt des Kopierens in eine Zeichenfolge. Oder, wenn Sie sich abenteuerlustig fühlen, können Sie Ihre eigene String-Klasse erstellen, die ermöglicht Ihnen, den internen Puffer auf die gleiche Weise, wie Vector tut.

+0

Wird std :: string Schreibzugriff auf einen zusammenhängenden Puffer in C++ 0x geben? – nobar

+0

Vektor von Char für Puffer ist veeeeery schlechte Idee, sehr ineffektiv. – Alecs

+0

@ Alecs: Könnten Sie ein wenig ausarbeiten? Meinst du, dass es nicht funktioniert, oder nur, dass es nicht die effizienteste Methode ist? – nobar

0

Ich habe hier einige über streambuffer der Erforschung, lesen Sie direkt auf Zeichenfolge aus istream von Baumeister:

class mystringbuf : public std::stringbuf 
{ 
public: 
    explicit mystringbuf(std::istream& istr, size_t n, 
         std::ios_base::openmode __mode = std::ios_base::in) 
    { 
     _M_string.resize(n); 
     std::stringbuf::_M_stringbuf_init(__mode); 
     istr.read(gptr(), n); 
    } 
public: 
    std::stringbuf::char_type* gptr() const 
    { 
     return std::stringbuf::gptr(); 
    } 
    std::string& str_ref(){ 
     return _M_string; 
    } 
}; 
std::ostream& operator << (std::ostream& ostr, mystringbuf& buf){ 
    ostr << buf.str_ref(); 
    return ostr; 
} 

Beispiel zu verwenden:

using std::cout; 
using std::endl; 

int main() 
{ 
    std::stringbuf buffer;   // empty buffer 
    buffer.str("abc def ABC DEF "); // not empty now 
    std::istream is (&buffer);  // associate stream buffer to stream 
    mystringbuf data(is, 10);  // read 10 bytes 
    cout << "data=" << data << endl; 
    return 0; 
} 

Ausgang:

data=abc def AB 

Bitte Schick mich weiter wenn ich irgendwo falsch liege.