Wie zu verwenden istream mit strings
Möchte ich zum Lesen einer Datei in einen string. Ich bin auf der Suche nach verschiedenen Möglichkeiten, wie es zu tun effizient.
Mit einer festen Größe *char Puffer
Ich habe eine Antwort von Tony was erstellt einen 16-kb-Puffer und liest sich in die Puffer und fügt den Puffer, bis es nichts mehr zu Lesen. Ich verstehe, wie es funktioniert und ich fand es sehr schnell. Was ich nicht verstehe ist, dass in den Kommentaren der Antwort wird es gesagt, dass auf diese Weise kopiert alles doppelt. Aber so wie ich es verstehe, es passiert nur im Speicher, nicht von der Festplatte, so ist es fast unnoticable. Ist es ein problem, dass es Kopien aus dem Puffer auf den string im Speicher?
Mit istreambuf_iterator
Den andere Antwort erhielt ich verwendet istreambuf_iterator. Der code sieht schön aus und minimal, aber es ist extrem langsam. Ich weiß nicht, warum geschieht es. Warum sind diese Iteratoren so langsam?
Mit memcpy()
Für diese Frage erhielt ich Kommentare, die ich verwenden soll, memcpy (), da es die Schnellste native Methode. Aber wie kann ich mit memcpy() mit einem string-und einem ifstream-Objekt? Nicht ifstream funktionieren soll mit seinen eigenen read-Funktion? Warum nicht mit memcpy (), Ruine Portabilität? Ich bin auf der Suche nach einer Lösung, die kompatibel ist mit VS2010 sowie GCC. Warum würde memcpy() nicht mit denen arbeiten?
+ Andere effiziente Art und Weise möglich?
Was empfehlen Sie, was muss ich verwenden, für kleine < 10 MB Binär-Dateien?
(Ich habe nicht teilen möchten, auf diese Frage in teilen, wie ich bin mehr daran interessiert, den Vergleich zwischen den unterschiedlichen Weg, wie kann ich Lesen ifstream in einen string)
- memcpy() Kommentar bezieht sich auf das Lesen mittels memory-mapped-Datei nicht Lesen mit istream. Memory-mapped-Datei ist nicht tragbar, weil es hängt davon ab, OS-API.
- Wenn Sie die Messung der Leistung, tun Sie es in der release-oder debug-Modus? Sie haben Optimierungen einschalten? Sie haben iterator-überprüfung ausgeschaltet ist? Standardmäßig visual studio hat extra-standard-iterator überprüfen, die können die Leistung beeinträchtigen.
- möglich, Duplikat der wie vorab reservieren Sie Speicher für ein std::string-Objekt? Vielleicht die genaue doppelte habe ich noch nicht gesehen. Der gesamte erste Satz ist praktisch identisch (der einzige Unterschied ist, dass "ich muss..." gegen "ich möchte...")
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dass ist ja richtig. Noch, eine Lösung, die nicht tun, die möglicherweise schneller sein.
Code ist langsam, nicht, weil Iteratoren, aber da der string nicht wissen, wie viel Speicher zu reservieren: die
istreambuf_iterator
s können nur einmal Durchlaufen werden, damit der string ist im wesentlichen gezwungen, um auszuführen, wiederholte Verknüpfungen mit den daraus resultierenden Speicher-Umschichtungen, die sehr langsam sind.Mein Lieblings one-liner, von eine andere Antwort streaming ist direkt von der darunterliegenden Puffer:
Auf den letzten Plattformen dies wird in der Tat pre-allocate buffer. Es wird allerdings noch das Ergebnis in einer redundanten Kopie (von der
stringstream
zum final string).Ganz allgemein wäre wohl die Antwort mit der
istreambuf_iterator
:Obwohl die genaue Leistung ist sehr abhängig von der Umsetzung, es ist
sehr unwahrscheinlich, dass dies die Schnellste Lösung.
Eine interessante alternative wäre:
Könnte dies sehr schnell, wenn die Umsetzung machen einen guten job auf
die
operator<<
Sie verwenden, und wie es wächst eine Zeichenfolge innerhalb deristringstream
. Einige frühere Implementierungen (und vielleicht sone mehrdie jüngsten, als auch) waren sehr schlecht darin, jedoch.
Im Allgemeinen, die Leistung mit einer
std::string
wird davon abhängen, wieeffizienter ist die Umsetzung immer ein string; die Umsetzung
können nicht bestimmen, wie groß, um es zunächst. Möchten Sie vielleicht
vergleichen Sie die erste Algorithmus, der den gleichen code mit
std::vector<char>
statt
std::string
oder, wenn Sie können machen Sie eine gute Schätzung dermaximale Größe, mit
reserve
oder so etwas wie:memcpy
können nicht aus einer Datei Lesen, und mit einem guten compiler, nichtso schnell wie mit
std::copy
(mit den gleichen Datentypen).Ich Neige dazu, verwenden Sie die zweite Lösung vor, mit der
<<
auf dierdbuf()
, aber das ist teilweise historisch bedingt; ich habetun dies (mit
istrstream
), bevor die STL wurde Hinzugefügt, um die standard -Bibliothek. Für diese Angelegenheit, möchten Sie vielleicht zu Experimentieren mit
istrstream
und einer bereits zugewiesenen Puffer übergeben wird (vorausgesetzt, Sie finden einepassende Größe für den Puffer).
source.seekg(0,std::ios_base::end); std::streampos pos=source.tellg(); source.seekg(0,std::ios_base::beg);
. Nach dieser, wennsource
ist noch Ok undpos!=-1
,pos
werden, z.B. die Größe einer Datei. Ich habe diese in der Vergangenheit.std::streampos
ist eine Implementierung definiert den Typ und das ist nicht unbedingt Cabrio auf einen integralen Typ. Und selbst wenn es Cabrio (es muss eine Klasse geben), gibt es keine Garantie mehr für eine Beziehung zwischen dem numerischen Wert der integer-und nichts anderes---es könnte ein magic cookie. Schließlich, Sie definieren nicht die Größe, aber in diesem Fall, was gewollt ist, ist die Anzahl der Zeichen, die gelesen werden, bevorEOF
. Und für diese definition, es funktioniert nicht unter Windows, es sei denn die Datei wird im Binärmodus geöffnet.std::streampos
nicht, sein Cabrio oder seinen Wert keine übertragung, keine Bedeutung könnte in der Tat ein show-stopper. Ich wusste nicht, über, die. Als für das, was als die Größe: der gemeldete Wert vontellg()
nicht in der gleichen Weise Binär/text, dass das streaming ist? (Allerdings, auch wenn es nicht, normalerweise wird dies über 10% der Dateigröße. Es könnte somit zu einer zusätzlichen Zuteilung anstatt eine willkürliche Menge.)tellg()
werden die gleichen sein für jede Datei, unabhängig davon, ob es geöffnet im text-Modus oder im binären. Die Anzahl der Zeichen, die Sie Lesen können, wird nicht die gleiche sein, jedoch. Für die Bestimmung der Puffergröße, könnte es ausreichend sein, da die Anzahl der Zeichen, die Sie Lesen können, werden immer kleiner oder gleich den Ergebnissen dertellg()
. In der Regel für die text-Modus-Dateientellg()
nicht zu viel größer als das, was man Lesen kann, aber es kann erheblich unterschiedlich sein.