Создал 2 метода:
Код:
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
Вопрос. Как объяснить полученые резутьтаты ???
Вы проверяете размер файла, перед тем как в него реально что либо запишется.
Обычно в таких случаях данные сначала хранятся в памяти, пока поток не достигнет какого либо лимита, или работа с ним не будет завершена, и только потом данные будут записаны в файл.
Например, если это какой нибудь архив со словарем вначале файла, то неизвестно в каком виде данные будут выглядеть окончательно.
Если необходимо немедленно отправить данные в файл, предусматривают метод 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());
}
}
Дело в том, что по умолчанию используется конструктор 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());
}
}
}
Сборка персонального компьютера от Artline: умный выбор для современных пользователей