HOWTO · C++

Wie man eine Datei Zeile für Zeile in C++ liest

In diesem Artikel werden wir vier gängige Ansätze zum zeilenweisen Lesen einer Datei in C++ untersuchen: die Verwendung von ifstream mit getline(), die getline()-Funktion aus der C-Bibliothek, die fgets()-Funktion und istream_iterator.

Auf dieser Seite

Das zeilenweise Lesen einer Datei in C++ ist eine grundlegende Operation bei vielen Programmieraufgaben, etwa bei der Datenverarbeitung, der Textanalyse und dem Parsen von Dateien. Ob Sie mit kleinen Textdateien oder großen Datensätzen arbeiten – zu wissen, wie diese Aufgabe geht, ist wichtig.

In diesem Artikel werden wir vier gängige Ansätze zum zeilenweisen Lesen einer Datei in C++ untersuchen: die Verwendung von ifstream mit getline(), die getline()-Funktion aus der C-Bibliothek, die fgets()-Funktion und istream_iterator.

Warum eine Datei Zeile für Zeile lesen

Eine Datei Zeile für Zeile zu lesen wird oft dem Lesen der gesamten Datei auf einmal vorgezogen, insbesondere beim Umgang mit großen Dateien. Indem Sie jeweils eine Zeile verarbeiten, können Sie den Speicherverbrauch effizient verwalten und Dateien praktisch beliebiger Größe handhaben.

Dieser Ansatz ist besonders nützlich für Aufgaben, bei denen Sie jede Zeile unabhängig verarbeiten müssen, etwa beim Parsen von CSV-Dateien, bei der Protokollverarbeitung oder bei der Textanalyse.

Hier ist eine Beispiel-Datei input.txt, die etwas Beispieltext enthält:

This is a sample input file.
It contains multiple lines of text.
Each line demonstrates a different scenario.
For example, this line contains numbers: 12345.
And this line has special characters: !@#$%^&*().

Verwenden wir diese Datei als Eingabe, um die Beispiele zum Lesen von Dateien in den folgenden Abschnitten zu testen.

Wie man eine Datei in C++ Zeile für Zeile mit ifstream und der Funktion getline() liest

Wenn es darum geht, eine Datei in C++ Zeile für Zeile zu lesen, besteht eine der einfachsten und am häufigsten verwendeten Methoden darin, die Klasse ifstream in Verbindung mit der Funktion getline() zu nutzen. Dieser Ansatz bietet Einfachheit und Effizienz beim Umgang mit Dateieingaben und ist daher für viele Entwickler die bevorzugte Wahl.

Die Funktion getline() ist Teil der C++-Standardbibliothek und wird hauptsächlich zum Lesen von Zeilen aus Eingabeströmen verwendet, etwa aus Dateien oder der Standardeingabe (cin).

Ihre Syntax lautet wie folgt:

istream& getline(istream& is, string& str, char delim);

Wobei:

  • is: Eingabestrom, aus dem die Zeichen gelesen werden sollen.
  • str: String-Variable, in der die extrahierten Zeichen gespeichert werden.
  • delim: Trennzeichen, das das Ende jeder Zeile markiert (Standard ist '\n').

Die Funktion getline() liest Zeichen aus dem Eingabestrom, bis sie auf das angegebene Trennzeichen trifft oder das Ende des Stroms erreicht. Anschließend speichert sie diese Zeichen in der bereitgestellten String-Variablen, ohne das Trennzeichen selbst.

Wichtig ist, dass getline() den Eingabestrom (is) zurückgibt, was die Verkettung mehrerer Eingabeoperationen ermöglicht.

Sehen wir uns nun ein Beispiel an, das zeigt, wie man eine Datei in C++ mit ifstream und getline() Zeile für Zeile liest:

#include <fstream>
#include <iostream>
#include <string>

int main() {
  std::ifstream file("input.txt");

  if (!file.is_open()) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  std::string line;

  while (std::getline(file, line)) {
    std::cout << line << std::endl;
  }

  file.close();

  return 0;
}

In diesem Beispiel beginnen wir damit, die notwendigen Header-Dateien einzubinden: <iostream>, <fstream> und <string>. Diese stellen Funktionalitäten für Ein-/Ausgabe, Datei-Streaming bzw. String-Manipulation bereit.

Anschließend definieren wir die Funktion main. Innerhalb der Funktion main wird eine Instanz von std::ifstream namens file erstellt, die den Eingabe-Dateistrom darstellt.

Dann versuchen wir, die Datei mit dem Namen "input.txt" über den Konstruktor der Datei zu öffnen. Schlägt das Öffnen der Datei fehl, wird eine Fehlermeldung in den Standardfehlerstrom (cerr) ausgegeben, und das Programm beendet sich mit einem Status ungleich null.

Als Nächstes deklarieren wir eine String-Variable line, um jede aus der Datei gelesene Zeile zu speichern. Innerhalb der while-Schleife rufen wir wiederholt std::getline() mit dem Dateistrom (file) und der String-Variablen (line) als Argumenten auf.

Diese Funktion liest eine Zeile aus dem Dateistrom, bis sie das Ende der Zeile oder das Ende der Datei erreicht. Jede gelesene Zeile wird dann in den Standardausgabestrom (cout) ausgegeben.

Nachdem alle Zeilen aus der Datei gelesen wurden, schließen wir schließlich den Dateistrom mit der Methode close(), um Systemressourcen freizugeben.

Ausgabe:

Eine Datei in C++ Zeile für Zeile mit ifstream und getline() lesen

Dies zeigt, wie man eine Datei in C++ mit ifstream und getline() effektiv Zeile für Zeile liest, und bietet eine klare und prägnante Methode für den Umgang mit Dateieingabeoperationen.

Wie man eine Datei in C++ Zeile für Zeile mit der Funktion getline() aus der C-Bibliothek liest

Zusätzlich zur C++-Standardbibliothek können C++-Entwickler auch die von der C-Bibliothek bereitgestellte Funktion getline() nutzen, um eine Datei Zeile für Zeile zu lesen. Obwohl diese Funktion etwas anders arbeitet, bietet sie eine brauchbare Alternative für den Umgang mit Dateieingabeoperationen.

Die Funktion getline() aus der C-Bibliothek wird hauptsächlich zum Lesen von Zeilen aus Eingabeströmen verwendet, ähnlich wie ihr Gegenstück in der C++-Standardbibliothek. Ihre Syntax lautet wie folgt:

ssize_t getline(char** lineptr, size_t* n, FILE* stream);

Hier:

  • lineptr: Ein Zeiger auf den Puffer, in dem die Zeile gespeichert wird.
  • n: Ein Zeiger auf die Variable, die die Größe des Puffers enthält (die bei Bedarf angepasst wird).
  • stream: Der Dateistrom, aus dem die Zeile gelesen werden soll.

Im Gegensatz zur getline()-Funktion der C++-Standardbibliothek gibt die Version der C-Bibliothek einen ssize_t-Wert zurück, der die Anzahl der gelesenen Zeichen angibt, oder -1, wenn ein Fehler auftritt oder das Ende der Datei erreicht wird.

Sehen wir uns ein Beispiel an, das zeigt, wie man eine Datei in C++ mit getline() aus der C-Bibliothek Zeile für Zeile liest:

#include <cstdio>
#include <cstdlib>
#include <iostream>

int main() {
  FILE* file = fopen("input.txt", "r");

  if (!file) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  char* line = nullptr;
  size_t len = 0;

  ssize_t read;
  while ((read = getline(&line, &len, file)) != -1) {
    std::cout << line;
  }

  free(line);

  fclose(file);

  return 0;
}

Zu Beginn sind die notwendigen Header-Dateien eingebunden: <iostream> für Ein-/Ausgabeoperationen, <cstdio> für Ein-/Ausgabe im C-Stil und <cstdlib> für Funktionen zur Speicherallokation.

In der Funktion main deklarieren wir einen FILE*-Zeiger namens file und versuchen, die Datei "input.txt" mit der Funktion fopen() im Lesemodus zu öffnen. Schlägt das Öffnen der Datei fehl, wird eine Fehlermeldung ausgegeben, und das Programm beendet sich mit einem Status ungleich null.

Anschließend deklarieren wir einen Zeichenzeiger line und eine size_t-Variable len, um jede aus der Datei gelesene Zeile bzw. ihre Länge zu speichern. Innerhalb der while-Schleife rufen wir wiederholt getline() mit dem Dateistrom (file), der Adresse des Zeigers line und der Adresse der Variablen len auf.

Diese Funktion liest eine Zeile aus dem Dateistrom, allokiert bei Bedarf dynamisch Speicher und speichert die Zeile in dem Puffer, auf den line zeigt. Jede gelesene Zeile wird dann in den Standardausgabestrom (cout) ausgegeben.

Nachdem alle Zeilen aus der Datei gelesen wurden, geben wir den dynamisch allokierten Speicher für den line-Puffer mit der Funktion free() frei und schließen den Dateistrom mit der Funktion fclose(), um Systemressourcen freizugeben.

Ausgabe:

Eine Datei in C++ Zeile für Zeile mit getline() aus der C-Bibliothek lesen

Dies zeigt eine alternative Methode zum zeilenweisen Lesen einer Datei in C++, die die Funktion getline() aus der C-Bibliothek nutzt.

Wie man eine Datei in C++ Zeile für Zeile mit der Funktion fgets() liest

Eine weitere Methode, eine Datei in C++ Zeile für Zeile zu lesen, besteht in der Verwendung der Funktion fgets(), die Teil der C-Standardbibliothek ist. Obwohl fgets() im Vergleich zu strombasierten C++-Ansätzen weniger intuitiv erscheinen mag, bietet es Einfachheit und Kompatibilität mit älteren Codebasen oder Szenarien, in denen Ein-/Ausgabe im C-Stil bevorzugt wird.

Die Syntax von fgets() lautet wie folgt:

char *fgets(char *str, int size, FILE *stream);

Hier:

  • str: Ein Zeiger auf das Zeichenarray (den Puffer), in dem die Zeile gespeichert wird.
  • size: Die maximale Anzahl der zu lesenden Zeichen (einschließlich des Nullterminators).
  • stream: Der Dateistrom, aus dem die Zeile gelesen werden soll.

Die Funktion gibt bei Erfolg str zurück oder NULL, wenn ein Fehler auftritt oder das Dateiende erreicht wird.

Fahren wir mit einem Beispiel fort, das veranschaulicht, wie man eine Datei in C++ mit fgets() Zeile für Zeile liest:

#include <cstdio>
#include <iostream>

int main() {
  FILE* file = fopen("input.txt", "r");

  if (!file) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  char line[256];

  while (fgets(line, sizeof(line), file) != NULL) {
    std::cout << line;
  }

  fclose(file);

  return 0;
}

In diesem Beispiel beginnen wir damit, die notwendigen Header-Dateien einzubinden: <iostream> für Ein-/Ausgabeoperationen und <cstdio> für Ein-/Ausgabe im C-Stil.

Innerhalb der Funktion main deklarieren wir einen FILE*-Zeiger namens file und versuchen, die Datei "input.txt" mit der Funktion fopen() im Lesemodus zu öffnen. Schlägt das Öffnen der Datei fehl, wird eine Fehlermeldung ausgegeben, und das Programm beendet sich mit einem Status ungleich null.

Anschließend definieren wir ein Zeichenarray line mit einer Größe von 256 Zeichen, um jede aus der Datei gelesene Zeile zu speichern. Innerhalb der while-Schleife rufen wir wiederholt fgets() mit dem Dateistrom (file), der Adresse des Arrays line und der Größe des Arrays auf.

Diese Funktion liest eine Zeile aus dem Dateistrom und speichert sie im Puffer line. Jede gelesene Zeile wird dann in den Standardausgabestrom (cout) ausgegeben.

Nachdem alle Zeilen aus der Datei gelesen wurden, schließen wir den Dateistrom mit der Funktion fclose(), um Systemressourcen freizugeben.

Ausgabe:

Eine Datei in C++ Zeile für Zeile mit fgets() lesen

Dies zeigt einen alternativen Ansatz zum zeilenweisen Lesen einer Datei in C++. Obwohl sich fgets() in Syntax und Verwendung etwas unterscheidet, bietet es eine brauchbare Option für den Umgang mit Dateieingabeoperationen und bietet Kompatibilität und Vertrautheit mit Programmierparadigmen im C-Stil.

Wie man eine Datei in C++ Zeile für Zeile mit istream_iterator liest

Der istream_iterator bietet eine elegante und moderne Möglichkeit, Daten aus Eingabeströmen, einschließlich Dateien, zu lesen, indem er den Strom als Folge von Elementen behandelt. Obwohl er typischerweise zum Lesen formatierter Daten wie Ganzzahlen oder Strings verwendet wird, kann er auch eingesetzt werden, um Zeilen aus einer Datei zu lesen, indem jede Zeile als String-Element behandelt wird.

Dieser Ansatz bietet Prägnanz und Lesbarkeit im Code und ist daher für viele Entwickler eine bequeme Wahl.

Die Syntax von istream_iterator lautet wie folgt:

istream_iterator<T> it(istream& is);

Hier:

  • T: Der Typ der zu lesenden Daten.
  • is: Der Eingabestrom, aus dem die Daten gelesen werden sollen.

Der Konstruktor von istream_iterator initialisiert einen Iterator (it), um über die aus dem Eingabestrom (is) extrahierten Elemente zu iterieren. Er wird typischerweise in Kombination mit den Dereferenzierungs- und Inkrementoperatoren von istream_iterator (*it bzw. ++it) verwendet, um auf die Elemente des Stroms zuzugreifen und sich durch sie zu bewegen.

Betrachten Sie das folgende Codebeispiel, das zeigt, wie man eine Datei in C++ mit istream_iterator Zeile für Zeile liest:

#include <fstream>
#include <iostream>
#include <iterator>
#include <string>

int main() {
  std::ifstream file("input.txt");

  if (!file.is_open()) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  std::istream_iterator<std::string> it(file);
  std::istream_iterator<std::string> end;

  if (it == end) {
    std::cerr << "Error: Empty file." << std::endl;
    return 1;
  }

  std::cout << *it++;

  while (it != end) {
    std::cout << " " << *it++;
  }
  std::cout << std::endl;

  file.close();

  return 0;
}

Zu Beginn sind die notwendigen Header-Dateien eingebunden: <iostream> für Ein-/Ausgabeoperationen, <fstream> für Datei-Streaming, <iterator> für Iteratoroperationen und <string> für String-Manipulation.

In der Funktion main deklarieren wir ein ifstream-Objekt namens file und versuchen, die Datei "input.txt" zu öffnen. Schlägt das Öffnen der Datei fehl, wird eine Fehlermeldung ausgegeben, und das Programm beendet sich mit einem Status ungleich null.

Anschließend erstellen wir einen istream_iterator namens it, der mit dem Dateistrom file initialisiert wird, um Strings aus der Datei zu lesen. Zusätzlich erstellen wir einen Iterator für das Stromende namens end, um das Ende der Datei zu kennzeichnen.

Innerhalb der while-Schleife iterieren wir mit dem Iterator it über den Dateiinhalt, bis er den Iterator für das Stromende end erreicht. Bei jeder Iteration dereferenzieren wir den Iterator (*it), um die aktuelle Zeile zu erhalten, geben sie auf der Konsole aus und rücken den Iterator dann weiter (++it).

Nachdem alle Zeilen aus der Datei verarbeitet wurden, schließen wir den Dateistrom mit der Methode close(), um Systemressourcen freizugeben.

Ausgabe:

Eine Datei in C++ Zeile für Zeile mit istream_iterator lesen

Dies zeigt eine alternative Methode zum zeilenweisen Lesen einer Datei in C++, die den istream_iterator nutzt, um den Dateiinhalt als Folge von Strings zu behandeln. Dieser Ansatz bietet eine moderne und prägnante Lösung für den Umgang mit Dateieingabeoperationen und verbessert die Lesbarkeit und Wartbarkeit des Codes.

Fazit

Wir haben mehrere Methoden zum zeilenweisen Lesen einer Datei in C++ untersucht, von denen jede ihre Vorteile und ihre Eignung je nach den spezifischen Anforderungen und Vorlieben des Programmierers bietet. Ob mit der getline()-Funktion aus der C++-Standardbibliothek, getline() aus der C-Bibliothek, fgets() oder istream_iterator – Entwickler haben eine Reihe von Optionen zur Auswahl.

Die getline()-Funktion bietet sowohl in der C++- als auch in der C-Bibliothek einen unkomplizierten Ansatz, während fgets() Kompatibilität mit der Programmierung im C-Stil bietet. Der istream_iterator hingegen stellt eine moderne und prägnante Lösung dar, um über den Dateiinhalt als Folge von Strings zu iterieren.

Unabhängig von der gewählten Methode bleibt das Hauptziel dasselbe: den Inhalt einer Datei effizient und genau Zeile für Zeile zu lesen. Indem wir die Syntax und die Mechanik jeder Methode verstehen, können wir den für unsere Projekte am besten geeigneten Ansatz auswählen und so eine effiziente Dateihandhabung und optimale Lesbarkeit des Codes gewährleisten.