Unformatierter Input

C++ bietet natürlich auch Möglichkeiten zum unformatierten Input. Die IOStreams haben dafür extra Schnittstellen, wie hier im Beispiel zum Lesen von Bytes blockweise.

Video

Quellcode

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
    istringstream is("Ein kleiner Test-Text.");

    char buffer[5] = { 0 };
    is.read(buffer, 3); 
    cout << buffer << endl;
    cout << "Position: " << is.tellg() << endl;
    is.seekg(12);
    is.read(buffer, 4);
    buffer[is.gcount()] = 0;
    cout << buffer << endl;
    cout << "Position: " << is.tellg() << endl;
    is.seekg(-5, ios_base::end);
    is.read(buffer, 4);
    cout << buffer << endl;
    cout << "Position: " << is.tellg() << endl;
}

Erklärung

Nicht immer will man Daten formatiert ein- und ausgeben. Manchmal soll es einfach zeichenweise sein. Dafür gibt es die Methode read(), die in einen Puffer eine bestimmte Anzahl an Zeichen einliest. Die Schnittstelle ist eng angelehnt an das Vorbild aus der C-Welt: der Aufrufer muss einen Puffer bereitstellen, in den die gelesenen Daten geschrieben werden. Die Methode versucht die angegebene Anzahl an Zeichen einzulesen (soweit möglich). Im Unterschied zur C-Variante liefert die Methode allerdings nicht die Menge an eingelesenen Zeichen zurück, sondern eine Referenz auf den Eingabestream. Dadurch kann man folgendes Idiom verwenden: while (is.read(...)) {... } um bspw. eine Datei komplett einzulesen. Die zurückgelieferte Referenz wird hierbei automatisch in einen bool umgewandelt. Die Interpretation ist einfach: ist der Stream noch lesbar, dann ergibt diese Umwandlung true, ansonsten false.

Um festzustellen, an welcher Stelle im Stream man sich gerade befindet, gibt es die Methode tellg(). Die liefert den Index des nächsten zu lesenden Zeichens gezählt vom Anfang des Streams. Abhängig von der Art des Streams kann man auch den zu lesenden Index setzen. Die dafür zuständige Methode seekg() kommt in zwei Varianten: einmal nimmt sie einen Parameter, welcher immer der Index vom Anfang des Streams aus gemessen ist, in der zweiten Variante nimmt sie einen zweiten Parameter, der die Referenz angibt, von der gezählt werden soll. Die drei möglichen Werte std::ios_base::beg, std::ios_base::cur und std::ios_base::end repräsentieren hier jeweils Anfang, aktuelle Position oder Ende des Streams. Wie in Zeile 19 zu sehen muss man vom Ende des Streams übrigens mit negativen Indizes arbeiten (sonst würde man hinter das Ende des Streams suchen, was unzulässig ist und daher fehlschlägt).

Da read() anders als die C-Variante nicht die Anzahl an gelesenen Zeichen zurückliefert, muss man die irgendwie anders erhalten. Dafür existiert die Methode gcount(). Diese liefert die Anzahl der gelesenen Zeichen bei der letzten unformatierten Eingabe zurück. Damit kann man zum Beispiel ermitteln, welche Teile eine Puffers wirklich bearbeitet werden müssen, weil sie auch mit Zeichen befüllt wurden.