Java FileInputStream ObjectInputStream достигает конца файла EOF - PullRequest
21 голосов
/ 13 апреля 2010

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

26 голосов
/ 13 апреля 2010

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

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

19 голосов
/ 13 ноября 2012

У меня была такая же проблема сегодня. Хотя вопрос довольно старый, проблема остается, и не было никакого чистого решения. Игнорирование 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++;
   }
6 голосов
/ 13 апреля 2010

Нет. Поймать EOFException и использовать это, чтобы завершить цикл.

2 голосов
/ 11 апреля 2018

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

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

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

1 голос
/ 07 декабря 2013

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

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

import java.io.Serializable;

public enum ObjectStreamStatus implements Serializable {
    EOF
}


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

0 голосов
/ 14 августа 2012

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

0 голосов
/ 03 ноября 2011

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

0 голосов
/ 13 апреля 2010

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

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

0 голосов
/ 13 апреля 2010

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

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

...