fstream: Blockweises Einlesen mit read so richtig?



  • Was ist eigentlich so schlimm daran wenn man while(!file.eof()) benutzt?

    Überall steht das das falsch ist, aber dabei wird doch nur einmal die Schleife zu oft ausgeführt, aber dann liest read halt 0 Zeichen. Das ist doch kein Problem oder?



  • Was haltet ihr von dieser Schleife? Ist das so in Ordnung? (funktionieren tuts)

    while(file.read(buffer, bufferSize).gcount() > 0)
    {
    	//
    }
    


  • Weiß das niemand wie man es "richtig" macht? 🙂



  • denker schrieb:

    Was ist eigentlich so schlimm daran wenn man while(!file.eof()) benutzt?

    Überall steht das das falsch ist, aber dabei wird doch nur einmal die Schleife zu oft ausgeführt, aber dann liest read halt 0 Zeichen. Das ist doch kein Problem oder?

    Ob das ein Problem ist oder nicht hängt davon ab, wie deine Verarbeitung der (nicht)-gelesenen Zeichen aussieht. Prinzipiell ist das Ganze erstmal nur ein Logikfehler. Ob daraus dann ein schwerwiegendes Problem wird hängt von der konkreten Situation ab. Auf der anderen Seite: Mach es doch einfach richtig. Das ist nämlich gar nicht schwieriger und du ersparst dir spätere Probleme.

    denker schrieb:

    Was haltet ihr von dieser Schleife? Ist das so in Ordnung? (funktionieren tuts)

    while(file.read(buffer, bufferSize).gcount() > 0)
    {
    	//
    }
    

    Das ist eine Möglichkeit. Ich wäre wohl etwas expliziter:

    while(file.read(buffer, bufferSize) && file.gcount() > 0)
    {
    	//
    }
    

    bzw:

    while(file.read(buffer, bufferSize))
    {
        process(buffer, file.gcount());
    }
    

    Weiß das niemand wie man es "richtig" macht?

    "Richtig" ist abhängig von dem was du erreichen willst. Zumindest ist deine Schleife schon mal nicht falsch.



  • Juhu danke. 🙂

    Also ich hatte das erst so verstanden das es immer zu Problemen wenn man while(!file.eof()) benutzt. Das ich aber keine Probleme damit bekommen hatte lag wohl daran das ich die Schleife verlassen hab wenn 0 Bytes gelesen wurden. 🙂

    Dann werde ich wohl die zweite Möglichkeit benutzen. Die ist besser lesbar obwohl die erste irgendwie elegant aussieht. 😉
    Ich wusste gar nicht das ich die beiden Sachen mit && verknüpfen kann, aber jetzt sehe ich file.read(buffer, bufferSize) wird wohl zu file.good().

    Deine dritte Möglichkeit hatte ich auch schon ausprobiert aber die ist glaube ich falsch. Dort wird das letzte Stück nicht eingelesen wenn die Dateigröße nicht genau ein Vielfaches der Puffergröße ist. Oder liegt der Fehler bei mir?



  • Ach das Zweite hat genau das selbe Problem wie das Dritte. 😞



  • Das Problem ist das wenn nicht mehr <Puffergröße> Zeichen vorhanden sind wird das fail bit gesetzt und die Schleife bricht ab.



  • geht auch ein

    while(file.good())
    {
        //...
    };
    if(!file.eof())
        //Fehler
    

    ?



  • HumeSikkins kannst du nochmal einen Kommentar dazu abgeben? 🙂

    Also ist dein Code falsch oder liegt der Fehler bei mir?

    Wenn ich bei Variante #2 und #3 nach der Schleife nochmal ein read und process mache dann ist alles in Ordnung, aber das ist ja unschön.

    @ness: War das an mich? 🤡



  • denker schrieb:

    HumeSikkins kannst du nochmal einen Kommentar dazu abgeben? 🙂

    Also ist dein Code falsch oder liegt der Fehler bei mir?

    Sorry, mein Fehler. Der Code ist falsch. Zumindest für den allgemeinen Fall.
    gcount braucht man ja genau deshalb, weil read auch mal weniger als die n geforderten Zeichen lesen kann. Nämlich z.B. genau dann, wenn die Dateigröße kein ganzzahliges Vielfaches von n ist. In diesem Fall werden im letzten Leseschritt nur m (0 < m < n ) Zeichen gelesen. Gleichzeitig wird beim Versuch n Zeichen zu lesen das eof-bit gesetzt, da am Ende keine n Zeichen mehr vorhanden sind (man liest über das Dateiende hinaus). Demzufolge bricht die Schleife ab, obwohl noch m Zeichen gelesen wurden. Die letzten m Zeichen stehen zwar im Puffer, werden aber nicht mehr bearbeitet.
    Die Schleife funktioniert nur korrekt für den Sonderfall n == 1. Deshalb ist eine Schleife à la:

    for (char c; in.get(c); ) {
        // mach was mit c
    }
    

    oder:

    for (int i; in >> i; ) {
        // mach was mit i
    }
    

    auch immer korrekt.

    Dein Vorschlag mit dem

    while(file.read(buffer, bufferSize).gcount() > 0)
    {
        //
    }
    

    ist also durchaus ok. Du solltest nur nach der Schleife noch prüfen, warum gcount 0 lieferte:

    while(file.read(buffer, bufferSize).gcount() > 0)
    {
        //
    } 
    if (file.eof()) {
       // ok. Datei komplett gelesen
    }
    else {
      // ups. read schlug aus einem anderen Grund fehl.
    }
    

Anmelden zum Antworten