Подтвердить что ты не робот

Как оценить размер zip файла в java перед его созданием

У меня есть требование, в котором я должен создать zip файл из списка доступных файлов. Файлы имеют разные типы, такие как txt, pdf, xml и т.д. Я использую классы java util для этого.

Требование здесь - поддерживать максимальный размер файла 5 мб. Я должен выбрать файлы из списка на основе метки времени, добавить файлы в zip, пока размер zip файла не достигнет 5 мб. Я должен пропустить оставшиеся файлы.

Пожалуйста, дайте мне знать, есть ли способ в java, где я могу заранее оценить размер файла zip без создания фактического файла?

Или существует ли какой-либо другой подход для обработки этого

4b9b3361

Ответ 1

Оберните свой ZipOutputStream в персонализированный OutputStream, названный здесь YourOutputStream.

  • Конструктор YourOutputStream создаст еще один ZipOutputStream (zos2), который обертывает новый ByteArrayOutputStream (baos)
    public YourOutputStream(ZipOutputStream zos, int maxSizeInBytes)
  • Если вы хотите записать файл с помощью YourOutputStream, он сначала напишет его на zos2
    public void writeFile(File file) throws ZipFileFullException
    public void writeFile(String path) throws ZipFileFullException
    и т.д...
  • если baos.size() находится под maxSizeInBytes
    • Записать файл в zos1
  • еще
    • закрыть zos1, baos, zos2 бросить исключение. Для исключения я не могу думать о уже существующем, если есть, использовать его, иначе создать собственное исключение IOException ZipFileFullException.

Вам нужно два ZipOutputStream, один для записи на вашем диске, один для проверки, превышает ли ваше содержимое более 5 МБ.

EDIT: на самом деле я проверил, вы не можете легко удалить ZipEntry.

http://download.oracle.com/javase/6/docs/api/java/io/ByteArrayOutputStream.html#size()

Ответ 2

+1 для Colin Herbert: добавьте файлы один за другим, либо создайте резервную копию предыдущего шага, либо удалите последний файл, если архив большой. Я просто хочу добавить некоторые детали:

Прогноз слишком ненадежный.. PDF может содержать несжатый текст и сжимать до 30% оригинала или содержать уже сжатый текст и изображения, сжимающий до 80%. Вам нужно будет проверить весь PDF для сжимаемости, в основном, чтобы сжать их.

Вы можете попробовать статистическое предсказание, но это может уменьшить количество неудачных попыток, но вам все равно придется реализовать выше рекомендации. Сначала пройдите с более простой реализацией и посмотрите, достаточно ли этого.

Кроме того, сжимайте файлы по отдельности, затем выберите файлы, которые не превышают 5 МБ, если они связаны друг с другом. Если распаковка также автоматизирована, вы можете связать zip файлы с одним несжатым zip файлом.

Ответ 3

Возможно, вы могли бы добавлять файл каждый раз, пока не достигнете предела 5 МБ, а затем отбросьте последний файл. Как @Gopi, я не думаю, что есть способ оценить его без фактического сжатия файла.

Конечно, размер файла не будет увеличиваться (или, может быть, немного из-за zip-заголовка?), так что по крайней мере у вас есть оценка "наихудшего случая".

Ответ 4

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

Ответ 5

Я сделал это один раз в проекте с известными типами ввода. Мы знали, что общие слова наши данные сжаты около 5: 1 (это был весь текст.) Итак, я бы проверил размер файла и разделил его на 5...

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

Все, что сказал, я заметил, что zip-приложения, такие как 7zip, создадут zip файл определенного размера (например, CD), а затем разделит zip на новый файл, как только он достигнет предела. Вы можете посмотреть на этот исходный код. Раньше я использовал версию командной строки этого приложения в коде. У них есть библиотека, которую вы можете использовать. Не уверен, насколько хорошо это будет интегрироваться с Java.

Для чего это стоит, я также использовал библиотеку SharpZipLib. Это было очень хорошо. Интересно, есть ли для него порт Java.

Ответ 6

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

            int maxSizeForAllFiles = 70000; // Read from property
        int sizePerFile = 22000; // Red from property
        /**
         * Iterate all attachment list to verify if ZIP is required
         */
        for (String attachFile : inputAttachmentList) {
            File file = new File(attachFile);
            totalFileSize += file.length();
            /**
             * if ZIP required ??? based on the size
             */
            if (file.length() >= sizePerFile) {
                toBeZipped = true;
                logger.info("File: "
                            + attachFile
                                + " Size: "
                                + file.length()
                                + " File required to be zipped, MAX allowed per file: "
                                + sizePerFile);
                break;
            }
        }
        /**
         * Check if all attachments put together cross MAX_SIZE_FOR_ALL_FILES
         */
        if (totalFileSize >= maxSizeForAllFiles) {
            toBeZipped = true;
        }
        if (toBeZipped) {
            // Zip Here iterating all attachments
        }

Ответ 7

Есть лучший вариант. Создайте фиктивный LengthOutputStream, который просто учитывает записанные байты:

public class LengthOutputStream extends OutputStream {

    private long length = 0L;

    @Override
    public void write(int b) throws IOException {
        length++;
    }

    public long getLength() {
        return length;
    }
}

Вы можете просто подключить LengthOutputStream к ZipOutputStream:

public static long sizeOfZippedDirectory(File dir) throws FileNotFoundException, IOException {
        try (LengthOutputStream sos = new LengthOutputStream();
            ZipOutputStream zos = new ZipOutputStream(sos);) {
            ... // Add ZIP entries to the stream
            return sos.getLength();
        }
    }

Объект LengthOutputStream подсчитывает байты заархивированного потока, но ничего не сохраняет, поэтому ограничение размера файла отсутствует. Этот метод дает точную оценку размера, но почти так же медленно, как создание ZIP файла.