Unformatierter Input (2)

C++ bietet eine nicht blockierende Variante von read() an. Deren Benutzung kann allerdings für Überraschungen sorgen.

Video

Quellcode

#include <iostream>
#include <fstream>
#include <thread>
#include <chrono>

using namespace std;

int main()
{
    char buffer[10];
    ifstream i("inputqueue");
    cerr << "read" << endl;
    i.read(buffer, 6);
    cerr << i.gcount() << " Zeichen eingegeben.\n";

    this_thread::sleep_for(chrono::seconds(3));
    
    cerr << "readsome" << endl;
    auto bytes = i.readsome(buffer, 6);
    cerr << bytes << " Zeichen eingegeben.\n";
}

Erklärung

Für den Fall, dass man beim Lesen aus einem Inputstream keinesfalls blockieren möchte (bspw. wenn dieser aus dem Netzwerk liest), bietet C++ die Methode readsome() an. Deren Schnittstelle ist fast genauso, wie die von read(): ein Pointer auf einen Puffer und die gewünschte Anzahl an Bytes. Im Unterschied zu read() liefert readsome() allerdings direkt die Anzahl an gelesenen Bytes zurück.

Der gravierendste Unterschied der beiden Methoden ist ihr Verhalten: während read() blockiert bis entweder die geforderte Menge an Bytes vorhanden sind oder der zugrundeliegende Puffer einen Fehler signalisiert (bspw. am Ende der Datei), kehrt readsome() sofort zurück und liefert lediglich die im zugrundeliegenden Puffer gerade vorhandenen Daten. An der Stelle wird es dann kompliziert: der Standard spezifiert nicht genauer, wie der zugrundeliegende Puffer zu diesen Daten kommt. eine völlig legitime Implementierung von readsome() liefert bspw. immer 0 Bytes zurück und löst niemals einen tatsächlichen Lesevorgang aus. Damit wird die Verwendung der Funktion hochgradig schwierig, ohne die Details der Pufferimplementierung zu kennen. Will man bspw. eine Datei komplett mittels readsome() einlesen, kann das schlicht und ergreifend unmöglich sein (da niemals Bytes von der Festplatte nachgefordert werden und man damit niemals wirklich vorwärts kommt).

Insgesamt ist readsome() also nur zu empfehlen, wenn über den zugrundeliegenden Puffer einiges bekannt ist und man die Verwendung unbedingt als notwendig erachtet (bspw. beim Lesen aus einem Netzwerkpuffer).