Ich muss eine Datei in eine Zeichenfolge kopieren. Ich brauche einen Weg, um Speicher für dieses String-Objekt vorzuladen und den Dateiinhalt direkt in den Speicher dieser Zeichenfolge zu lesen.wie Speicherplatz für ein Std :: String-Objekt vorab reservieren?
Antwort
std::string
also has a .reserve
method.
Dies sollte alles, was Sie brauchen werden:
ostringstream os;
ifstream file("name.txt");
os << file.rdbuf();
string s = os.str();
Dieses liest Zeichen aus file
und fügt sie in die string. Danach wird die hinter den Kulissen erstellte Zeichenfolge abgerufen. Beachten Sie, dass ich in die folgende Falle geriet: Die Verwendung des Extraktionsoperators überspringt den anfänglichen Leerraum. Sie haben die Ausgabe-Operator wie oben zu verwenden, oder verwenden Sie die noskipws
Manipulator:
// Beware, skips initial whitespace!
file >> os.rdbuf();
// This does not skip it
file >> noskipws >> os.rdbuf();
Diese Funktionen wie das Lesen der Strom zeichenweise obwohl beschrieben werden (nicht sicher, welche Optimierungen möglich sind hier, obwohl), i haven‘ t Zeit diese um ihre Geschwindigkeit zu bestimmen.
+1 schlägt mich. :( – GManNickG
dies kopiert zweimal, einmal zu 'ostringstream' Puffer und zweites Mal zu' s' –
@Johannes, nahm ich an, dass der Schnurspeicher ansteckender Puffer ist, aber nach dem Lesen von @GMan 's Antwort realisierte ich, dass es nein gibt Um die Kopie herum: –
Just for fun, hier ist eine andere Art und Weise, dies zu tun:
// Beware, brain-compiled code ahead!
std::ifstream ifs(/* ... */);
if(!ifs.good()) return; // whatever
std::string str;
ifs.seekg(0, std::ios_base::end);
const std::streampos pos = ifs.tellg();
ifs.seekg(0, std::ios_base::beg);
if(pos!=std::streampos(-1)) // can get stream size?
str.reserve(static_cast<std::string::size_type>(pos));
str.assign(std::istream_iterator<char>(ifs)
, std::istream_iterator<char>());
ich, dass ich es so schlecht nicht hoffen blasen.
+1, wartete auf jemanden, um Stream Iterator-basierte Code zu erarbeiten :) – bobah
+1, für flexible 'Brain-Compiler' ist in Ordnung mit fehlenden'} ';) –
@Gollum: Ich gebe frei zu, dass ich diese 'seekg()' Zeilen direkt aus irgendeinem Code von mir kopiert habe (der einen String mit dem Inhalt einer Datei füllt) und das '{'. Ich habe es behoben, aber dafür ist der Disclaimer sowieso gedacht. – sbi
Dies ist nicht so eine Antwort in sich selbst, als eine Art Kommentar zu/Zusammenfassung/Vergleich von ein paar anderen Antworten (sowie eine kurze Demonstration, warum ich den Stil des Codes @ empfohlen habe @ Johannes - litb gibt in seiner Antwort). Da @sbi eine Alternative gepostet hat, die ziemlich gut aussah, und (besonders) die zusätzliche Kopie beim Einlesen in einen Stringstream vermied und dann das .str()
Mitglied benutzte, um eine Zeichenfolge zu erhalten, entschied ich mich, einen schnellen Vergleich der beiden zu schreiben:
[Bearbeiten: Ich habe einen dritten Testfall mit @Tyler McHenry istreambuf_iterator
-basierten Code hinzugefügt und eine Zeile hinzugefügt, um die Länge der einzelnen gelesenen Zeichenfolge auszudrucken, um sicherzustellen, dass der Optimierer nicht die Lesung optimiert weil das Ergebnis wurde nie verwendet]
[Edit2:. Und jetzt, Code von Martin Yorker wurde auch ...]
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
#include <iterator>
#include <time.h>
int main() {
std::ostringstream os;
std::ifstream file("equivs2.txt");
clock_t start1 = clock();
os << file.rdbuf();
std::string s = os.str();
clock_t stop1 = clock();
std::cout << "\ns.length() = " << s.length();
std::string s2;
clock_t start2 = clock();
file.seekg(0, std::ios_base::end);
const std::streampos pos = file.tellg();
file.seekg(0, std::ios_base::beg);
if(pos!=std::streampos(-1))
s2.reserve(static_cast<std::string::size_type>(pos));
s2.assign(std::istream_iterator<char>(file), std::istream_iterator<char>());
clock_t stop2 = clock();
std::cout << "\ns2.length = " << s2.length();
file.clear();
std::string s3;
clock_t start3 = clock();
file.seekg(0, std::ios::end);
s3.reserve(file.tellg());
file.seekg(0, std::ios::beg);
s3.assign((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
clock_t stop3 = clock();
std::cout << "\ns3.length = " << s3.length();
// New Test
std::string s4;
clock_t start4 = clock();
file.seekg(0, std::ios::end);
s4.resize(file.tellg());
file.seekg(0, std::ios::beg);
file.read(&s4[0], s4.length());
clock_t stop4 = clock();
std::cout << "\ns4.length = " << s3.length();
std::cout << "\nTime using rdbuf: " << stop1 - start1;
std::cout << "\nTime using istream_iterator: " << stop2- start2;
std::cout << "\nTime using istreambuf_iterator: " << stop3 - start3;
std::cout << "\nTime using read: " << stop4 - start4;
return 0;
}
hinzugefügt
Jetzt der beeindruckende Teil - die Ergebnisse. Zuerst mit VC++ (falls jemand kümmert, Martin Code ist schnell genug, ich die Dateigröße eine sinnvolle Zeit für sie zu bekommen erhöht):
s.length() = 7.669.436
s2.length = 6.390.688
s3.length = 7669436
s4.length = 7669436
Zeit unter Verwendung von RDBUF: 184
Zeit unter Verwendung von istream_iterator: 1332
Zeit unter Verwendung von istreambuf_iterator: 249
Zeit gelesen werden: 48
dann mit gcc (cygwin):
s.length() = 8278035
s2.length = 6390689
s3.length = 8278035
s4.length = 8.278.035
Zeit mit RDBUF: 62
Zeit mit istream_iterator: 2199
Zeit mit istreambuf_iterator: 156
Zeit ausgelesen: 16
[Ende bearbeiten - die Schlussfolgerungen bleiben, obwohl der Gewinner sich geändert hat - Martins Code ist klar der schnellste. ]
Die Ergebnisse sind ziemlich konsistent in Bezug auf die schnellste und langsamste. Die einzige Inkonsistenz ist, wie viel schneller oder langsamer ist als ein anderer. Obwohl die Platzierungen die gleichen sind, sind die Geschwindigkeitsunterschiede viel größer mit gcc als mit VC++.
Eine Art von dem, was ich anfangs dachte: Es ist viel einfacher, das char-by-char-Lesen von op << in einen Block zu lesen (oder inline entsprechende Teile) als das char-by-char-Lesen von istream_iterator (obwohl dieser Code muss) Verwenden Sie 'istreambuf_iterator', um das Überspringen von Leerraum für jedes gelesene Zeichen zu vermeiden - vielleicht wird das die Dinge beschleunigen, da es auf einer niedrigeren Ebene stattfindet?), die mehrere Schritte mit op ++, op * usw. durchläuft * Das * ein großer Unterschied. Danke für das Timing! –
Können Sie schreiben, welche Kompilierungsflags für Testfälle verwendet wurden? – tomekpe
Es scheint, dass Sie fragen, wie eine Operation CString :: GetBuffer, ReleaseBuffer Typ mit Std :: string.
Ich kenne keine Möglichkeit, dies direkt zu tun, eine einfache Möglichkeit wäre, nur einen rohen C-Style-Puffer zu erstellen, in den Puffer zu lesen und dann den Puffer mit assign oder was auch immer in eine std :: string zu kopieren . Natürlich müssten Sie sich über Pufferüberlaufprobleme usw. Sorgen machen, außerdem würde ich einen std :: autoptr verwenden, um den unformatierten Pufferzeiger zu verwalten, um die Freigabe für eine Ausnahme freizugeben usw. Dies ist etwas einfacher als die Verwendung von Stringstream usw. ein Beispiel, falls benötigt.
Devin Ellingson
'auto_ptr' behandelt Array-Typen nicht korrekt. Verwenden Sie einfach 'std :: vector'. (Auch das Signieren von Posts ist verpönt; Ihr Name steht unter allem, was Sie tun.) – GManNickG
Danke GMan, ich habe dieses Problem vergessen, auto_ptr ruft immer delete statt delete [] auf, was in diesem Fall nötig wäre. Sie könnten einfach eine einfache array_auto_ptr Klasse erstellen oder wie Sie sagen, std :: vector verwenden. – DevinEllingson
- 1. Wie viel Speicherplatz sollte ich für mein Subversion-Repository reservieren?
- 2. Reservieren von Speicherplatz auf dem iPhone
- 3. Speicherplatz im Browser-Layout für reaktionsfähige Bilder reservieren (Reflow verhindern)
- 4. Wie viel reservieren moderne Dateisysteme für jede Blockgruppe?
- 5. Ruby on Rails-Paket installieren Konnte keinen Speicherplatz für Cygwin-Heap reservieren
- 6. Wie reserviere ich Speicher für einen std :: Vektor zur Konstruktionszeit?
- 7. Wie reservieren Sie dynamisch Speicher für ein Char-Array in C++?
- 8. std :: back_inserter für ein std :: set?
- 9. So laden Sie ein AVPlayerItem vorab
- 10. Wann Speicher für ein Array in C++ reservieren?
- 11. Wie kann ich in C Speicherplatz für meine Struktur zuweisen?
- 12. Wie ist std :: function für ein Lambda
- 13. Reservieren von Speicher für DMA-Verwendung
- 14. Vorabzuweisen (reservieren) einer Prioritätswarteschlange <vector>?
- 15. posix_memalign für std :: vector
- 16. Mehrere Audiodateien vorab laden
- 17. Gewusst wie: Bild in GWT vorab abrufen?
- 18. Speicherplatz optimierte Lösung für Münzwechsel
- 19. Iphone Speicher in initWithNibName reservieren
- 20. Gibt es ein "unput" für std :: ostream, wie es existiert "get" für std :: istream?
- 21. Bildschirmbereich in Windows 7 reservieren
- 22. vorbelegen Speicherplatz für Programme verwenden
- 23. Wie std :: vector verkleinern?
- 24. Rebinding in einem benutzerdefinierten STL Zuordner mit vorab zugewiesenen Block
- 25. std :: copy std :: cout für std :: pair
- 26. Bilder vorab laden mit jquery
- 27. Reservieren Sie Speicher für eine Liste in Python?
- 28. Wie für eine std :: tuple
- 29. Wie mache ich ein variadic Makro für std :: cout?
- 30. Wie setze ich ein Präfix für std :: ostream_iterator?
möglich Duplikat [Lesen ganze ASCII-Datei in C++ std :: string] (http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring) - Meine akzeptierte Antwort auf diese Frage erklärt auch, wie der gesamte Speicher vorbelegt wird, so dass sich der String während des Lesens nicht wiederholt ausdehnt. –