Подтвердить что ты не робот

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

Я пытаюсь прочитать количество строк в двоичном файле с помощью readObject, но я получаю EOF IOException. Правильно ли я делаю это?

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

Ответ 1

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

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

Ответ 2

У меня была такая же проблема сегодня. Хотя вопрос довольно старый, проблема остается, и не было никакого чистого решения. Игнорирование EOFException следует избегать, поскольку оно может быть выброшено, если какой-то объект был сохранен неправильно. Написание 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++;
   }

Ответ 3

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

Ответ 4

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

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

import java.io.Serializable;

public enum ObjectStreamStatus implements Serializable {
    EOF
}


Затем в коде, считывающем объект, который я проверил для этого объекта EOF в цикле чтения объекта.

Ответ 5

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

Другим вариантом является вызов ois.available() и loop, пока он не вернет 0. Однако я не уверен, что это на 100%.

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

Просто добавьте: out.writeObject(null);

когда вы сериализуете данные.

Ответ 9

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