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++;
}
любопытно, что 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