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% уверен.
похоже, проблема в данных, которые вы написали. Предполагая, что данные записаны так, как ожидалось этим кодом, проблемы не должно быть.
(Я вижу, Вы читаете String
s. Это ObectInputStream
Не для чтения текстовых файлов. Использовать InputStreamReader
и BufferedReader.readLine
для этого. Аналогично, если вы написали файл с DataOutputSteam.writeUTF
, читать DataInputStream.readUTF
)
доступный метод ObjectInputStream не может использоваться для завершения цикла, поскольку он возвращает 0, даже если в файле есть объекты для чтения. Запись null в файл не кажется хорошим решением, так как объекты могут быть null, которые затем будут интерпретироваться как конец файла. Я думаю, что поймать EOFException для завершения циклов-лучшая практика, так как если eofexception происходит(либо потому, что вы достигли конца файла, либо по какой-либо другой причине), вы должны завершить все равно петля.
Если вы пишете нулевой объект в конце файла, когда вы читаете его обратно, вы получите нулевое значение и может завершить свой цикл.
просто добавить: из.writeObject (null);
при сериализации данных.
наилучший способ завершить цикл может быть сделан путем добавления нулевого объекта в конце. При чтении нулевого объекта можно использовать в качестве граничного условия для выхода из цикла. Ловля EOFException также решает цель, но для этого требуется несколько m