2010-04-12 10 views
17

Я пытаюсь прочитать количество строк в двоичном файле с помощью readObject, но я получаю EOF IOException. Правильно ли я делаю это?Java FileInputStream ObjectInputStream достигает конца файла 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

Я делаю то же самое, но я закрываю активный журнал. Я бы хотел, чтобы он подождал, пока на нем написано больше данных, но скажите мне, когда это будет написано. Я не уверен, есть ли способ сделать это, не поймав исключение. (Хвостовая часть работает нормально, она просто выводит ее, когда она выполняется, это меня подталкивает) –

ответ

22

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

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

+3

Если последний «объект», записанный в поток, был «null», вы бы прочитали «нулевой» ссылочный штраф. Это нормально для 'null', чтобы быть частью серийной формы, и есть специальное представление для него в последовательном формате. «Нуль» в конце, или какой-то другой дозорный, намного чище, чем подсчет. –

+0

Спасибо, я только что написал null после того, как все содержимое так сообщило, где был конец файла. Он работал префектом. – user69514

+0

Но это не делает этого, если вы не предполагаете, что никогда не писали нуль в любой другой точке. * Правильный ответ заключается в том, чтобы поймать EOFException и использовать * that * для завершения цикла. – EJP

0

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

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

+0

«Нет, вам нужно знать, сколько объектов есть в двоичном файле». Нет, нет. «Я не уверен, что это на 100% уверен». Это не так. В этом Jabadoc есть конкретное заявление. – EJP

0

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

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

+2

Неверный. EOFException является нормальным, и если он не написал нуль, нет причин прекращать цикл с нулевым значением, поэтому его цикл неверен. – EJP

+0

@EJP Вы что ?! Почему бы не написать «null», если ожидается, что «нуль» будет прочитан? –

+0

Это точно моя точка зрения. Если вы хотите, чтобы нуль читался, напишите нуль. Если вы хотите, чтобы EOFException был пойман, закройте поток. Это два разных действия. Конфляция их не служит никакой полезной цели. – EJP

6

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

+1

Насколько это опасно? Глава и стихи, пожалуйста. В любом случае, как я уже сказал здесь, у вас нет альтернативы, если вы не написали «null» в ObjectOutputStream, и в этом случае вы удаляете все другие полезные действия этого действия. – EJP

+4

Tom 1. Пожалуйста, прекратите вафли и ответьте на вопрос. Сообщите нам, что именно «опасно»: catch (EOFException exc) { break; } 2. Расскажите, пожалуйста, как читать весь ObjectInputStream, не перехватывая EOFException и не ограничивая автора этого потока тем, как это сделать. Вы не можете. Это невозможно. EOFException - единственный механизм. – EJP

-1

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

+4

Вы отвечаете, кажется, неполным, последнее предложение не заканчивается – oers

+0

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

0

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

+0

Метод 'available()' не может быть использован для этой цели *, потому что это не то, для чего он нужен. * См. Javadoc. – EJP

18

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

Это работает только в том случае, если ObjectInputStream не выполняет никакой буферизации. Это так? Javadoc ничего не говорит об этом. –

+0

available() не является допустимым тестом для конца потока. См. Javadoc. – EJP

+0

Как это должно помочь? один вызов метода, 'ois.readObject()', который выдает ошибку, все равно будет вызываться в вашем примере и, таким образом, выдает ошибку. по крайней мере, это не сработало для меня ..:/ – Blauhirn

1

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

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

import java.io.Serializable; 

public enum ObjectStreamStatus implements Serializable { 
    EOF 
} 


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

+1

API * не может * предоставить «более элегантное решение, чем это». Требуется результат вне диапазона. Исключение - единственная возможность. – EJP