2016-07-28 15 views
0

Ich schreibe ein C++ 14-Programm, um Textzeichenfolgen aus einer Datei zu laden, einige Berechnungen an ihnen durchzuführen und in eine andere Datei zurückzuschreiben. Ich benutze Linux und die Dateien sind relativ groß (O (10^6 Zeilen)). Mein typischer Ansatz dazu ist die Verwendung der alten C getline und sscanf Dienstprogramme zum Lesen und Parsen der Eingabe und fprintf(FILE*, …) zum Schreiben der Ausgabedateien. Das funktioniert, aber ich frage mich, ob es einen besseren Weg mit den Zielen der hohen Leistung und allgemein empfohlenen Annäherung mit dem modernen C++ - Standard gibt, den ich verwende. Ich habe gehört, dass iostream ziemlich langsam ist; Wenn das stimmt, frage ich mich, ob es einen empfohlenen Ansatz gibt.C++ - Hochleistungs-Datei lesen und schreiben (C++ 14)

Update: Um ein wenig über den Anwendungsfall zu verdeutlichen: Für jede Zeile der Eingabedatei mache ich einige Textmanipulationen (Datenbereinigung, etc.). Jede Zeile ist unabhängig. Es scheint also am sinnvollsten zu sein, die gesamte Eingabedatei (oder zumindest große Teile davon) zu laden und Zeile für Zeile zu verarbeiten und dann zu schreiben. Die ideale Abstraktion dafür wäre, einen Iterator in den eingelesenen Puffer zu bekommen, wobei jede Zeile ein Eintrag ist. Gibt es eine empfohlene Möglichkeit, dies mit Std :: Ifstream zu tun?

+1

auf dem Weg Je Sie Ihre Eingabedatei (sequentiell oder nicht) zuzugreifen, eine mit File Mapping API könnte Ihnen einige Vorteile bringen. Nicht sicher, wie es in der Linux-Welt heißt - was ich auf Windows-Plattformen bezeichne, heißt '' CreateFileMapping() '' und Familie von Funktionen. – BitTickler

+1

Es hängt davon ab, was Sie mit den Zeilen tun wollen, die Sie lesen (eine Kopie im Speicher behalten oder nicht) und welche Art von Analyse Sie machen. Es würde sich lohnen, ein paar Schnipsel zu zeigen. Auch diese [Antwort auf eine andere Frage] (http://stackoverflow.com/a/33444050/3723423) könnte Sie interessieren; Es befasst sich nicht mit dem Scannen, aber es behandelt einige andere Leistungsaspekte mit einem Link zu einem Benchmark-Code. – Christophe

+2

Wenn Sie den Speicher zu haben, lesen Sie die gesamte Datei in einem Puffer in 1 lesen, verarbeiten Sie es im Speicher, und schreiben Sie alles wieder in 1 schreiben. Wenn nicht, benutze eine [memory mapped file] (https://en.wikipedia.org/wiki/Memory-maped_file) – David

Antwort

3

Die schnellste Option, wenn Sie über den Speicher verfügen, ist das Lesen der gesamten Datei in einen Puffer mit 1 Lesen, Verarbeiten des Puffers im Speicher und erneutes Schreiben mit 1 Schreibvorgang.

es Alles lesen:

std::string buffer; 

std::ifstream f("file.txt"); 
f.seekg(0, std::ios::end); 
buffer.resize(f.tellg()); 
f.seekg(0); 
f.read(buffer.data(), buffer.size()); 

Dann verarbeiten es

es dann schreiben alle:

std::ofstream f("file.txt"); 
f.write(buffer.data(), buffer.size()); 
+0

Ich erwarte, dass dies schneller als File Mapped IO ist. Es ersetzt nur fred() mit Seitenfehlern. –

+1

Wenn die Datei ausreichend groß ist und der Speicherdruck für den physischen Speicher hoch ist, liest dieser Code die Datei zweimal von der Festplatte. – IInspectable

+0

Ich halte es für eine * mutige * Antwort, ohne die absolute Größe der Datei und den verfügbaren Speicher zu kennen ... –