Java FileInputStream ObjectInputStream достигает конца файла EOF

Я пытаюсь прочитать количество строк в двоичном файле с помощью readObject, но я получаю IOException 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++;
    }

9 ответов


readObject() не отвечает null в EOF. Вы могли бы поймать EOFException и интерпретировать его как EOF, но это не сможет обнаружить отличить обычный EOF от файла, который был усечен.

лучшим подходом было бы использовать некоторые мета-данные. То есть, вместо того, чтобы спрашивать ObjectInput сколько объектов находится в потоке, вы должны сохранить счет где-то. Например, можно создать класс метаданных, который записывает count и другие метаданные и сохраняет экземпляр как первый объект в каждом файле. Или вы можете создать специальный класс маркеров EOF и сохранить экземпляр в качестве последнего объекта в каждом файле.


у меня была та же проблема сегодня. Хотя вопрос довольно старый, проблема остается, и не было никакого чистого решения. Игнорирование EOFException следует избегать, поскольку он может быть брошен, когда какой-либо объект не был сохранен правильно. Очевидно, что запись null не позволяет использовать значения null для любых других целей. Наконец, используя available() в потоке объектов всегда возвращается ноль, так как количество объектов неизвестно.

мое решение довольно простое. ObjectInputStream - это всего лишь оболочка для другого потока, например FileInputStream. Хотя ObjectInputStream.available () возвращает ноль, FileInputStream.available вернет некоторое значение.

   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++;
   }

нет. Лови EOFException и используйте это для завершения цикла.


любопытно, что API не предоставляет более элегантного решения для этого. Я думаю EOFException будет работать, но меня всегда поощряли видеть исключения как неожиданные события, тогда как здесь вы часто ожидаете, что поток объектов закончится.

Я попытался обойти это, написав своего рода объект" маркер", чтобы обозначить конец потока объектов:

import java.io.Serializable;

public enum ObjectStreamStatus implements Serializable {
    EOF
}


затем в коде чтения объекта я проверил этот объект EOF в объекте цикл чтения.


нет, вам нужно знать, сколько объектов есть в двоичный файл. Вы можете записать количество объектов в начале файла (например, с помощью writeInt) и прочитать его при загрузке.

другой вариант-вызвать ois.available () и цикл, пока он не вернет 0. Однако я не уверен, что это 100% уверен.


похоже, проблема в данных, которые вы написали. Предполагая, что данные записаны так, как ожидалось этим кодом, проблемы не должно быть.

(Я вижу, Вы читаете Strings. Это ObectInputStream Не для чтения текстовых файлов. Использовать InputStreamReader и BufferedReader.readLine для этого. Аналогично, если вы написали файл с DataOutputSteam.writeUTF, читать DataInputStream.readUTF)


доступный метод ObjectInputStream не может использоваться для завершения цикла, поскольку он возвращает 0, даже если в файле есть объекты для чтения. Запись null в файл не кажется хорошим решением, так как объекты могут быть null, которые затем будут интерпретироваться как конец файла. Я думаю, что поймать EOFException для завершения циклов-лучшая практика, так как если eofexception происходит(либо потому, что вы достигли конца файла, либо по какой-либо другой причине), вы должны завершить все равно петля.


Если вы пишете нулевой объект в конце файла, когда вы читаете его обратно, вы получите нулевое значение и может завершить свой цикл.

просто добавить: из.writeObject (null);

при сериализации данных.


наилучший способ завершить цикл может быть сделан путем добавления нулевого объекта в конце. При чтении нулевого объекта можно использовать в качестве граничного условия для выхода из цикла. Ловля EOFException также решает цель, но для этого требуется несколько m