Das zeilenweise Lesen einer Datei in C++ kann auf verschiedene Arten erfolgen.
[Fast] Schleife mit std::getline()
Der einfachste Ansatz besteht darin, einen std::ifstream zu öffnen und mit std::getline()-Aufrufen eine Schleife zu bilden. Der Code ist sauber und leicht zu verstehen.
#include <fstream>
std::ifstream file(FILENAME);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
file.close();
}
[Fast] Boosts file_description_source verwenden
Eine andere Möglichkeit ist die Verwendung der Boost-Bibliothek, aber der Code ist dann etwas ausführlicher. Die Leistung ist dem obigen Code recht ähnlich (Schleife mit std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
namespace io = boost::iostreams;
void readLineByLineBoost() {
int fdr = open(FILENAME, O_RDONLY);
if (fdr >= 0) {
io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
io::stream <io::file_descriptor_source> in(fdDevice);
if (fdDevice.is_open()) {
std::string line;
while (std::getline(in, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
fdDevice.close();
}
}
}
[Schnellste] C-Code verwenden
Wenn die Leistung Ihrer Software entscheidend ist, sollten Sie die Sprache C verwenden. Dieser Code kann 4-5 mal schneller sein als die obigen C++-Versionen, siehe Benchmark unten
FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
exit(EXIT_FAILURE);
char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
// using printf() in all tests for consistency
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
Benchmark - Wer ist schneller?
Ich habe einige Leistungsvergleiche mit dem obigen Code durchgeführt und die Ergebnisse sind interessant. Ich habe den Code mit ASCII-Dateien getestet, die 100.000 Zeilen, 1.000.000 Zeilen und 10.000.000 Zeilen Text enthalten. Jede Textzeile enthält im Durchschnitt 10 Wörter. Das Programm ist kompiliert mit -O3
Optimierung und ihre Ausgabe wird weitergeleitet an /dev/null
um die Variable der Aufzeichnungszeit aus der Messung zu entfernen. Zu guter Letzt protokolliert jedes Codestück jede Zeile mit der printf()
Funktion für Konsistenz.
Die Ergebnisse zeigen die Zeit (in ms), die jeder Code zum Lesen der Dateien benötigte.
Der Leistungsunterschied zwischen den beiden C++-Ansätzen ist minimal und sollte in der Praxis keinen Unterschied machen. Die Leistung des C-Codes ist das, was den Benchmark beeindruckend macht und in Bezug auf die Geschwindigkeit ein entscheidender Faktor sein kann.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms