Вопрос по сериализации в Java

158
28 июля 2019, 04:20

В классе ObjectInput есть метод available(), который, как написано в java docs, возвращает количество байт, доступных для чтения без блокировки. В классе FileInputStream этот метод возвращает корректное количество байт, а тут всегда 0, хотя для чтения есть байты. В связи с этим вопросы:

  1. Что значит без блокировки, и почему метод возвращает 0, хотя в файле есть непрочитанные сериализованные объекты?
  2. Как делать проверку, есть ли в файле данные(объекты) для считывания?
Answer 1

без блокировки значит, что при запросе такого количества байт поток, исполняющий запрос не будет приостановлен до получения новой порции данных. Т.е. это значит, что в стриме гарантировано есть available байт.

Метод available() возвращает оценочное количество байт для чтения без блокировки. Например, для InputStream он всегда возвращает 0. Видимо, стрим, на котором ты реализуешь десереализацию, по каким-то внутренним причинам не может вернуть точное количество доступных байт, поэтому он возвращает 0 (что тоже валидное значение, говорящее о том, что нет гарантии, что твой вызов закончится без блокировки).

Из файла читаем все доступные объекты, ловя EOFException:

try(FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis))
{
    while(true)
    {
        try
        {
            SerializableClass sc = (SerializableClass) ois.readObject();
            /// ... do some additional work
        }
        catch (EOFException ignore)
        {
            break;
        }
    }
}
Answer 2

Джавадок неверен.

available возвращает число байт записанных в поток методом write(byte[]).

Вот небольшой пример для иллюстрации.

public class App {
    public static void main(String[] args) {
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream stream = new ObjectOutputStream(out);
            stream.writeObject(A.builder().i(1).j(2).build());
            stream.write(new byte[7]);
            stream.close();
            ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
            System.out.println("available = " + inputStream.available());
            System.out.println("o = " + inputStream.readObject());
            System.out.println("available = " + inputStream.available());
            System.out.println("byte = " + inputStream.read());
            System.out.println("available = " + inputStream.available());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    @Data
    @Builder
    static class A implements Serializable {
        int i;
        int j;
    }
}
READ ALSO
Не отображается иконка при свайпе CardView

Не отображается иконка при свайпе CardView

При свайпе вправо не отображается иконка, хотя при свайпе влево она естьЯ смог пофиксить это, деля итоговое число на 10, но иконка получается...

151
gradle сборка зависимостей отдельно

gradle сборка зависимостей отдельно

Есть проект, который использует много библиотекЯ хочу передавать его на другой ПК после каждого обновления

156
Актуальность аплетов

Актуальность аплетов

В книге Шилда "Java 8 для начинающих" пару раз разбирается создание аплетов разными средствамиРазве сейчас, эти аплеты не вытеснены JavaScript'ом?...

148
Как правильно нарисовать на Jpanel?

Как правильно нарисовать на Jpanel?

у меня есть главное окно(MainFrame), где меню, таблица и тд, и есть свободное место, куда размещено пустой JPANEL(MainDrawPanel), я хочу туда нарисовать фигуры

169