2010-04-12 17 views
17

Ich versuche, die Anzahl der Zeile in einer Binärdatei mit readObject zu lesen, aber ich bekomme IOException EOF. Mache ich das richtig?Java FileInputStream ObjectInputStream erreicht Ende der Datei EOF

FileInputStream istream = new FileInputStream(fileName); 
    ObjectInputStream ois = new ObjectInputStream(istream); 

    /** calculate number of items **/ 
    int line_count = 0; 
    while((String)ois.readObject() != null){    
     line_count++; 
    } 
+0

Ich mache das gleiche - aber ich bin ein aktives Protokoll. Ich möchte es warten, bis mehr Daten da sind, solange das Programm schreibt, aber sagen Sie mir, wenn es fertig ist zu schreiben. Ich bin nicht sicher, ob es einen Weg gibt, dies zu tun, ohne die Ausnahme zu fangen. (Der Tailing-Teil funktioniert gut, es wird nur zum Beenden gebracht, wenn es fertig ist, das nervt mich) –

Antwort

22

readObject() kehrt nicht null bei EOF. Sie könnten die EOFException abfangen und sie als EOF interpretieren, aber dies würde keinen normalen EOF von einer Datei unterscheiden, die abgeschnitten wurde.

Ein besserer Ansatz wäre die Verwendung einiger Metadaten. Das heißt, anstatt die ObjectInput Frage, wie viele Objekte im Stream sind, sollten Sie die Zählung irgendwo speichern. Sie können beispielsweise eine Metadatenklasse erstellen, die die Anzahl und andere Metadaten aufzeichnet und eine Instanz als erstes Objekt in jeder Datei speichert. Oder Sie könnten eine spezielle EOF-Markierungsklasse erstellen und eine Instanz als letztes Objekt in jeder Datei speichern.

+3

Wenn das letzte 'Objekt', das in den Stream geschrieben wurde, 'null' ist, dann liest man die 'Null'-Referenzstrafe. Es ist normal, dass 'null's ein Teil der seriellen Form sind, und es gibt eine spezielle Darstellung dafür im seriellen Format. Ein "Null" am Ende, oder ein anderer Wächter, ist viel sauberer als eine Zählung. –

+0

Danke Ich habe nur null geschrieben, nachdem alle Inhalte so Signal, wo das Ende der Datei war. Es funktionierte Präfekt. – user69514

+0

Das geht aber nicht, es sei denn, Sie nehmen an, dass Sie an keiner anderen Stelle eine Null geschrieben haben. Die * korrekte * Antwort ist, EOFException abzufangen und * das * zu verwenden, um die Schleife zu beenden. – EJP

0

Nein, Sie müssen wissen, wie viele Objekte in der Binärdatei vorhanden sind. Sie könnten die Anzahl der Objekte am Anfang der Datei schreiben (z. B. mit writeInt) und sie beim Laden lesen.

Eine weitere Option ist es, ois.available() aufzurufen und eine Schleife zu machen, bis es 0 zurückgibt. Ich bin mir jedoch nicht sicher, ob das 100% sicher ist.

+0

'Nein, Sie müssen wissen, wie viele Objekte in der Binärdatei vorhanden sind'. Nein, tust du nicht. "Ich bin mir nicht sicher, ob das hundertprozentig sicher ist." Es ist nicht. Dazu gibt es im Javadoc eine spezifische Aussage. – EJP

0

Es sieht aus wie das Problem mit den Daten ist, die Sie ausgeschrieben haben. Unter der Annahme, dass die Daten wie erwartet von diesem Code geschrieben werden, sollte es kein Problem geben.

(ich sehe Sie lesen String s. Diese ObectInputStream Textdateien nicht zum Lesen ist. Verwenden Sie InputStreamReader und BufferedReader.readLine dafür. Ebenso, wenn Sie die Datei mit DataOutputSteam.writeUTF geschrieben haben, lesen Sie es mit DataInputStream.readUTF)

+2

Falsch. EOFException ist normal, und wenn er kein NULL geschrieben hat, gibt es keinen Grund, die Schleife bei null zu beenden, so dass seine Schleife falsch ist. – EJP

+0

@EJP Du was ?! Warum sollte kein "Null" geschrieben werden, wenn erwartet wird, dass ein "Null" gelesen wird? –

+0

Das ist genau mein Punkt. Wenn Sie möchten, dass eine Null gelesen wird, schreiben Sie eine Null. Wenn Sie möchten, dass EOFException abgefangen wird, schließen Sie den Stream. Dies sind zwei verschiedene Aktionen. Ihre Zusammenführung dient keinem nützlichen Zweck. – EJP

6

Nein Fangen Sie EOFException und verwenden Sie das, um die Schleife zu beenden.

+1

Wie genau ist es gefährlich? Kapitel und Vers bitte. In jedem Fall, wie ich bereits hier gesagt habe, haben Sie keine Alternative, es sei denn, Sie schreiben eine 'Null' in den ObjectOutputStream, in diesem Fall entfernen Sie alle anderen nützlichen Anwendungen dieser Aktion. – EJP

+4

Tom 1. Bitte hören Sie auf zu waffeln und beantworten Sie die Frage. Sagen Sie uns genau, was "gefährlich" ist: catch (EOFException exc) { break; } 2. Bitte sagen Sie uns, wie Sie einen gesamten ObjectInputStream lesen können, ohne EOFException abzufangen und ohne den Writer dieses Streams einzuschränken, wie es gemacht wird. Du kannst nicht. Es kann nicht gemacht werden. EOFException ist der einzige Mechanismus. – EJP

-1

Die beste Möglichkeit zum Beenden der Schleife könnte durch Hinzufügen eines Null-Objekts am Ende erfolgen. Das Lesen des Nullobjekts kann als Randbedingung zum Verlassen der Schleife verwendet werden. Das Abfangen der EOFException löst auch den Zweck, aber es dauert wenige m

+4

Ihre Antwort scheint unvollständig zu sein, der letzte Satz endet nicht – oers

+0

Und was Sie bisher geschrieben haben, ist inkorrekt, da es unmöglich ist, null an einem anderen Ort zu schreiben. – EJP

0

Die verfügbare Methode von ObjectInputStream kann nicht zum Beenden der Schleife verwendet werden, da es 0 zurückgibt, auch wenn Objekte in einer Datei gelesen werden sollen. Das Schreiben einer Null in eine Datei scheint keine gute Lösung zu sein, da Objekte null sein können und dann als das Ende der Datei interpretiert werden. Ich denke, die EOFException zu fangen, um die Schleifen zu beenden, ist eine bessere Praxis, da, wenn EOFException auftritt (entweder weil Sie das Ende der Datei oder aus einem anderen Grund erreicht haben), Sie die Schleife sowieso beenden müssen.

+0

Die Methode 'available()' kann nicht für diesen Zweck verwendet werden *, weil das nicht der Fall ist. * Siehe Javadoc. – EJP

18

Ich hatte das gleiche Problem heute. Obwohl die Frage ziemlich alt ist, bleibt das Problem bestehen und es gab keine saubere Lösung. Ignorieren EOFException sollte vermieden werden, da es geworfen werden kann, wenn ein Objekt nicht korrekt gespeichert wurde. Das Schreiben von null verhindert offensichtlich, dass Sie für andere Zwecke Nullwerte verwenden. Schließlich gibt available() für den Objektstrom immer Null zurück, da die Anzahl der Objekte unbekannt ist.

Meine Lösung ist ziemlich einfach. ObjectInputStream ist nur ein Wrapper für einen anderen Stream, z. B. FileInputStream. Obwohl ObjectInputStream.available() Null zurückgibt, gibt FileInputStream.available einen Wert zurück.

FileInputStream istream = new FileInputStream(fileName); 
    ObjectInputStream ois = new ObjectInputStream(istream); 

    /** calculate number of items **/ 
    int line_count = 0; 
    while(istream.available() > 0) // check if the file stream is at the end 
    { 
     (String)ois.readObject(); // read from the object stream, 
            // which wraps the file stream 
     line_count++; 
    } 
+0

Dies funktioniert nur, wenn ObjectInputStream keine Pufferung durchführt. Ist das der Fall? Das Javadoc sagt nichts darüber aus. –

+0

available() ist kein gültiger Test für das Ende des Streams. Sieh den Javadoc. – EJP

+0

wie soll das helfen? Der eine Methodenaufruf 'ois.readObject()', der den Fehler auslöst, wird in Ihrem Beispiel immer noch aufgerufen und löst somit einen Fehler aus. zumindest funktionierte es bei mir nicht ..:/ – Blauhirn

1

Es ist merkwürdig, dass die API nicht eine elegantere Lösung dieses Problems nicht liefert.Ich denke, die EOFException würde funktionieren, aber ich wurde immer ermutigt, Ausnahmen als unerwartete Ereignisse zu sehen, während Sie hier oft erwarten würden, dass der Objektstrom zu einem Ende kommt.

Ich habe versucht, dies zu umgehen, indem eine Art von „Marker“ Objekt zu schreiben, das Ende des Objekts Strom zu bedeuten:

import java.io.Serializable; 

public enum ObjectStreamStatus implements Serializable { 
    EOF 
} 


Dann im Code das Objekt zu lesen i in der für dieses EOF Objekt geprüft Objektleseschleife.

+1

Die API * kann keine 'elegantere Lösung als diese' bieten. Ein Out-of-Band-Ergebnis ist erforderlich. Eine Ausnahme ist die einzige Möglichkeit. – EJP

Verwandte Themen