Serialization в java

285
18 ноября 2018, 11:50

Создал 2 метода:

  1. Пишет 1 и тот же объект несколько раз в 1 и тот же txt файл
  2. Пишет 1 и тот же объект несколько раз в 1 и тот же zip файл

Код:

private void serializeRepoToTxt(ProductRepository repository) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("products.txt"))) {
            for (int i = 0; i < 9; i++) {
                oos.writeObject(repository);
                LOGGER.trace(new File("products.txt").length());
            }
        }
    }
    private void serializeRepoToZip(ProductRepository repository) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream("products.gz")))) {
            for (int i = 0; i < 9; i++) {
                oos.writeObject(repository);
                LOGGER.trace(new File("products.gz").length());
            }
        }
    }

На каждой итерации цикла логгер выводит размер файла, в который поток пишет

Результаты txt -> 1034 1039 1044 1049 1054 1059 1064 1069 1074

Результаты zip -> 10 10 10 10 10 10 10 10 10

Вопрос. Как объяснить полученые резутьтаты ???

Answer 1

Вы проверяете размер файла, перед тем как в него реально что либо запишется.

Обычно в таких случаях данные сначала хранятся в памяти, пока поток не достигнет какого либо лимита, или работа с ним не будет завершена, и только потом данные будут записаны в файл.

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

Если необходимо немедленно отправить данные в файл, предусматривают метод flush(), но даже он, иногда может быть проигнорирован (например случай архива со словарем вначале).

Попробуйте с обычным файлом:

private void serializeRepoToTxt(ProductRepository repository) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("products.txt"))) {
        for (int i = 0; i < 9; i++) {
            oos.writeObject(repository);
            oos.flush(); //Скидываем в файл
            LOGGER.trace(new File("products.txt").length());
        }
        oos.close(); //Скидываем остатки в файл, которых нет
        LOGGER.trace(new File("products.txt").length());
    }
}

Не уверен, что с архивом получиться:

private void serializeRepoToZip(ProductRepository repository) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream("products.gz")))) {
        for (int i = 0; i < 9; i++) {
            oos.writeObject(repository);
            //Не думаю что с архивом так стоит делать
            //oos.flush(); 
            //LOGGER.trace(new File("products.gz").length());
        }
        oos.close(); //Скидываем все в файл
        LOGGER.trace(new File("products.gz").length());
    }
}
Answer 2

Дело в том, что по умолчанию используется конструктор GZIPOutputStream(out, false), где второй параметр указывает на то, что

syncFlush - если true, то вызов унаследованного метода flush() этого экземпляра сбрасывает компрессор с режимом очистки Deflater.SYNC_FLUSH перед очисткой выходного потока, в противном случае только очищает выходной поток.

этим и объясняются полученные результаты. Попробуйте поменять второй параметр и посмотрите насколько изменится выходной файл, возможно вам также надо облегчить компрессию, иcпользуя уровень компресии NO_COMPRESSION, чтобы результаты были более наглядными.

если даже это не помогает, то попробуйте finish():

Завершает запись сжатых данных в выходной поток без закрытия базового потока. Используйте этот метод при одновременном применении нескольких фильтров к одному и тому же потоку вывода.

используя код:

private void serializeRepoToZip(ProductRepository repository) throws IOException {
    try (GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream("products.gz")); 
        ObjectOutputStream oos = new ObjectOutputStream(gos)) {
        for (int i = 0; i < 9; i++) {
            oos.writeObject(repository);
            gos.finish();
            LOGGER.trace(new File("products.gz").length());
        }
    }
}
READ ALSO
Как организовать конвертацию моделей?

Как организовать конвертацию моделей?

Например для вьюхи может быть не нужны все поля модели и для неё будет лучше использовать специальную обрезанную модель

191
Проблема с CheckBox в Диалоговом окне

Проблема с CheckBox в Диалоговом окне

Я хочу сделать кастомное диалоговое окно, и вроде всё хорошо, но метод findViewById на CheckBox не работаетНе знаю в чём проблема и соответственно, как...

220
Обращение к приватному методу извне

Обращение к приватному методу извне

Есть задача, в которой нужно поэкспериментировать с объектами типа CatМы создали 5 кошек и делаем с ними разные вещи

224
Открыть layout поверх

Открыть layout поверх

Подскажите, как можно открыть лейаут нажатием на кнопкуМне не нужно открывать новый класс:

222