Wie verwende ich istream mit Strings?

8

Ich möchte eine Datei in eine Zeichenfolge lesen. Ich suche nach verschiedenen Wegen, wie man es effizient macht.

Verwenden eines Zeichenpuffers fester Größe *

Ich habe eine Antwort erhalten von Tony, was einen 16-kb-Puffer erzeugt und in diesen Puffer liest und den Puffer anhängt, bis nichts mehr zu lesen ist. Ich verstehe, wie es funktioniert und ich fand es sehr schnell. Was ich nicht verstehe ist, dass in den Kommentaren dieser Antwort gesagt wird, dass auf diese Weise alles zweimal kopiert wird. Aber wie ich es verstehe, passiert es nur in der Erinnerung, nicht von der Festplatte, also ist es fast unbemerkt. Ist es ein Problem, dass es aus dem Puffer in die Zeichenfolge im Speicher kopiert?

Verwenden von istreambuf_iterator

Die andere Antwort Ich habe verwendet istrebuf_iterator. Der Code sieht schön und minimal aus, aber er ist extrem langsam. Ich weiß nicht, warum es passiert. Warum sind diese Iteratoren so langsam?

Verwenden von memcpy ()

Für diese Frage erhielt ich Kommentare, dass ich Memcpy () verwenden sollte, da es die schnellste native Methode ist. Aber wie kann ich memcpy () mit einer Zeichenfolge und einem ifstream-Objekt verwenden? Soll ifstream nicht mit einer eigenen Lesefunktion arbeiten? Warum zerstört die Verwendung von memcpy () die Portabilität? Ich suche nach einer Lösung, die sowohl mit VS2010 als auch mit GCC kompatibel ist. Warum sollte memcpy () nicht mit diesen arbeiten?

+ Jeder andere effiziente Weg möglich?

Was empfehlen Sie, welche Shell ich verwende, für kleine & lt; 10 MB Binärdateien?

(Ich wollte diese Frage nicht in Teilen aufteilen, da ich mich mehr für den Vergleich zwischen den verschiedenen Möglichkeiten interessiere, wie ich einen ifstream in eine Zeichenkette einlesen kann)

    
zsero 28.06.2011, 17:53
quelle

2 Antworten

7
  

es passiert nur im Speicher, nicht von der Festplatte, so ist es fast unbemerkt

Das ist in der Tat richtig. Dennoch kann eine Lösung, die das nicht tut, schneller sein.

  

Warum sind diese Iteratoren so langsam?

Der Code ist langsam, nicht wegen der Iteratoren, sondern weil die Zeichenfolge nicht weiß, wieviel Speicher zuzuweisen ist: Die istreambuf_iterator s kann nur einmal durchlaufen werden, sodass die Zeichenfolge im Wesentlichen gezwungen wird, wiederholte Verkettungen mit resultierenden Speicherumverteilungen durchzuführen , die sehr langsam sind.

Mein Lieblings-Einzeiler, von eine andere Antwort streamt direkt aus dem zugrunde liegenden Puffer:

%Vor%

Auf neueren Plattformen wird dies in der Tat den Puffer vorab reservieren. Dies führt jedoch immer noch zu einer redundanten Kopie (von stringstream bis zur letzten Zeichenfolge).

    
Konrad Rudolph 28.06.2011, 18:13
quelle
3

Der allgemeinste Weg wäre wahrscheinlich die Antwort mit dem istreambuf_iterator :

%Vor%

Obwohl die genaue Leistung sehr von der Implementierung abhängt, ist es das sehr unwahrscheinlich, dass dies die schnellste Lösung ist.

Eine interessante Alternative wäre:

%Vor%

Das könnte sehr schnell gehen, wenn die Implementierung einen guten Job gemacht hat das operator<< , das du benutzt, und wie es die Zeichenkette innerhalb der %Code%. Einige frühere Implementierungen (und vielleicht noch mehr auch die jüngsten) waren sehr schlecht.

Im Allgemeinen hängt die Leistung mit istringstream davon ab, wie Effizient die Implementierung ist in einer wachsenden Reihe; die Umsetzung kann nicht bestimmen, wie groß es anfangs sein soll. Sie möchten vielleicht vergleiche den ersten Algorithmus mit dem gleichen Code mit std::string anstelle von std::vector<char> , oder wenn Sie eine gute Schätzung der maximale Größe, mit std::string , oder etwas wie:

%Vor%

reserve kann nicht aus einer Datei lesen, und mit einem guten Compiler wird es nicht sein So schnell wie memcpy verwenden (mit den gleichen Datentypen).

Ich neige dazu, die obige zweite Lösung mit dem std::copy auf der << , aber das ist teilweise aus historischen Gründen; ich habe mich daran gewöhnt tue dies (mit rdbuf() ), bevor die STL zum Standard hinzugefügt wurde Bibliothek. Vielleicht möchten Sie experimentieren istrstream und ein vorher zugeordneter Puffer (vorausgesetzt, Sie können ein geeignete Größe für den Puffer).

    
James Kanze 28.06.2011 18:11
quelle