Как оценить размер zip файла в java перед его созданием
У меня есть требование, в котором я должен создать zip файл из списка доступных файлов. Файлы имеют разные типы, такие как txt, pdf, xml и т.д. Я использую классы java util для этого.
Требование здесь - поддерживать максимальный размер файла 5 мб. Я должен выбрать файлы из списка на основе метки времени, добавить файлы в zip, пока размер zip файла не достигнет 5 мб. Я должен пропустить оставшиеся файлы.
Пожалуйста, дайте мне знать, есть ли способ в java, где я могу заранее оценить размер файла zip без создания фактического файла?
Или существует ли какой-либо другой подход для обработки этого
Ответы
Ответ 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, 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 файла.