2016-08-03 48 views
-1

Wenn ich dies tun:Wie kann ich erkennen, dass eine Binärdatei vollständig konsumiert wurde?

ofstream ouput("foo.txt"); 

output << 13; 
output.close(); 

ifstream input("foo.txt"); 
int dummy; 

input >> dummy; 

cout << input.good() << endl; 

ich das Ergebnis bekommen: "0"

Allerdings, wenn ich dies tun:

ofstream ouput("foo.txt", ios_base::binary); 
auto dummy = 13; 

output.write(reinterpret_cast<const char*>(&dummy), sizeof(dummy)); 
output.close(); 

ifstream input("foo.txt", ios_base::binary); 

input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy)); 
cout << input.good() << endl; 

Ich werde das Ergebnis: „1 "

Das ist frustrierend für mich. Muss ich den Puffer ifstream untersuchen, um festzustellen, ob er vollständig verbraucht wurde?

+0

@Downvoter Bitte geben Sie den Grund für den Downvote an. –

+1

Versuchen Sie, die Dateien für die binäre Ausgabe und Eingabe zu öffnen. – Peter

+0

@Peter Ugh, habe das lokal gemacht. Kopieren Sie einfach für die Antwort eingefügt. –

Antwort

0

Sie müssen nicht auf die Überprüfung des Puffers zurückgreifen. Sie können bestimmen, ob die gesamte Datei verbraucht wurde: cout << (input.peek() != char_traits<char>::eof()) << endl Dies verwendet: peek, die:

das nächste Zeichen aus dem Eingangsstrom Liest ohne es zu extrahieren

good im Fall des Beispiels ist :

  • false nach dem letzten Extraktionsvorgang zurückkehrend, die aufgrund des int-Operator auftritt hat zu lesen, bis es ein Zeichen findet th Bei ist keine Ziffer. In diesem Fall, dass das EOF-Zeichen ist, und wann wird das Zeichen auch als Trennzeichen der Strom des eofbit gesetzt ist, liest good verursacht
  • Rückkehr true nach read Aufruf zum Scheitern verurteilt, weil read Extrakte genau sizeof(int) -bytes so, auch wenn die EOF-Zeichen ist das nächste Zeichen wird es nicht lesen, so dass der Strom des eofbit Frisch- und good vorbei

peek kann nach einer dieser beiden verwendet und korrekt zurückkehren char_traits<char>::eof() in beiden Fällen. Effektiv prüft dies den Puffer für Sie, aber mit einer wichtigen Unterscheidung für Binärdateien: Wenn Sie eine Binärdatei selbst untersuchen würden, würden Sie feststellen, dass sie das EOF-Zeichen enthalten kann. (Auf den meisten Systemen, die als 0xFF definiert sind, davon 4 in der binären Darstellung von -1.) Wenn Sie das nächste Zeichen des Puffers prüfen, wissen Sie nicht, ob das tatsächlich das Ende der Datei ist oder nicht.

peek gibt nicht nur eine char zurück, es gibt auch eine int_type zurück.Wenn peek 0x000000FF zurückgibt, dann betrachten Sie ein EOF-Zeichen, aber nicht das Ende der Datei. Wenn peekchar_traits<char>::eof() (normalerweise 0xFFFFFFFF) zurückgibt, dann schauen Sie auf das Ende der Datei.

0

Sie machen ganz andere Dinge.

Die operator>> ist gierig und wird so viel wie möglich in dummy lesen. Es passiert so, dass es dabei am Ende der Datei läuft. Das setzt die input.eof(), und der Stream ist nicht mehr good(). Da es einige Ziffern vor dem Ende gefunden hat, ist die Operation immer noch erfolgreich.

In der zweiten Lesung, fragen Sie nach einer bestimmten Anzahl von Bytes (4 am wahrscheinlichsten) und das Lesen ist erfolgreich. So ist der Stream immer noch good().

Die Stream-Schnittstelle sagt nicht das Ergebnis von zukünftigen I/O voraus, weil es im allgemeinen Fall nicht wissen kann. Wenn Sie cin anstelle von input verwenden, könnte es jetzt mehr zu lesen geben, wenn der Benutzer weiter tippt.

Der Status eof() wird nicht angezeigt, bis jemand versucht, das letzte Dateiende zu lesen.

+0

Ja, das habe ich verstanden. Ich denke, Sie sagen, der einzige Weg, um herauszufinden, ob die Datei leer ist, besteht darin, den Puffer zu überprüfen. –

+0

Oder weiterlesen, bis der Lesevorgang fehlschlägt. Dann überprüfe, dass 'eof()' wahr ist (und nicht 'bad()'). –

0

Für Text-Streams, da Sie beim Lesen nur den Ganzzahlwert und nicht einmal ein Leerzeichen geschrieben haben, muss die Bibliothek versuchen, ein Zeichen zu lesen, das die Zeichen 1 und 3 passiert hat und das Ende der Datei erreicht . Also ist das gute Bit falsch und das EOF ist wahr.

Für binäre Datenströme haben Sie 4 Byte geschrieben (sizeof (int)), vorausgesetzt, ints sind 32 Bits groß und Sie lesen 4 Bytes. Fein. Kein Problem ist noch aufgetreten und das gute Bit ist wahr und falsch. Nur der nächste Lesevorgang wird das Ende der Datei erreichen.

Aber Vorsicht. Wenn Sie in einem Beispiel die Textdatei in einem Editor öffnen und sie einfach speichern, ohne etwas zu ändern, besteht die Möglichkeit, dass der Editor automatisch ein Zeilenende hinzufügt. In diesem Fall wird der Lesevorgang am Ende der Zeile angehalten, und für den Binärfall wird das gute Bit wahr und falsch sein. Gleiches gilt für output << 13 << std::endl;

All dies bedeutet, dass Sie niemals davon ausgehen sollten, dass ein Lesevorgang nicht das letzte Element einer Datei ist, wenn es true und eof falsch ist, da das Dateiende nur beim nächsten Lesevorgang betroffen sein kann auch wenn dann nichts zurückgegeben wird.

TL/DR: Die einzige idiotensichere Möglichkeit zu wissen, dass in einer Datei nichts mehr enthalten ist, wenn Sie nicht mehr in der Lage sind, etwas daraus zu lesen.

+0

Ja, das habe ich verstanden. Ich denke, Sie sagen, der einzige Weg, um herauszufinden, ob die Datei leer ist, besteht darin, den Puffer zu überprüfen. –

+0

@ JonathanMee Nicht genau. Ich sage, dass Sie einen folgenden Lesevorgang durchführen könnten, um das Ende der Datei zu erkennen. –

1

In Bezug auf

Wie kann ich erkennen, dass eine Binary Datei wird vollständig verbraucht?

Ein etwas ineffizient, aber leicht zu verstehen Weg ist, um die Größe der Datei zu messen:

ifstream input("foo.txt", ios_base::binary); 
input.seekg(0, ios_base::end); // go to end of the file 
auto filesize = input.tellg(); // current position is the size of the file 
input.seekg(0, ios_base::beg); // go back to the beginning of the file 

Dann aktuelle Position überprüfen, wann immer Sie wollen:

if (input.tellg() == filesize) 
    cout << "The file was consumed"; 
else 
    cout << "Some stuff left in the file"; 

Auf diese Weise hat einige Nachteile :

  • Nicht effizient - geht zurück und fo rth in der Datei
  • Funktioniert nicht mit speziellen Dateien (z. Rohre)
  • funktioniert nicht, wenn die Datei (zB Öffnen Sie die Datei im Lese-Schreib-Modus)
  • funktioniert nur für binäre Dateien (erscheint Ihr Fall, so OK), nicht Textdateien
geändert wird

So verwenden besser, nur die regelmäßige Art, wie Menschen es tun, das heißt, versuchen zu lesen und zu retten, wenn es fehlschlägt:

if (input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy))) 
    cout << "I have read the stuff, will work on it now"; 
else 
    cout << "No stuff in file"; 

Or (in einer Schleife)

while (input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy))) 
{ 
    cout << "Working on your stuff now..."; 
}