Каков размер буфера для создания ZIP-архива с использованием Java?
Вопрос
Я использую этот код для создания ZIP-файла со списком файлов:
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
for (int i=0;i<srcFiles.length;i++){
String fileName=srcFiles[i].getName();
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
InputStream fis = new FileInputStream(srcFiles[i]);
int read;
for(byte[] buffer=new byte[1024];(read=fis.read(buffer))>0;){
zos.write(buffer,0,read);
}
fis.close();
zos.closeEntry();
}
zos.close();
Я не знаю, как работает алгоритм zip и ZipOutputStream. Если он что-то записывает до того, как я прочитаю и отправлю в «zos» все данные, размер файла результатов может отличаться от размера в байтах, чем если бы я выбрал другой размер буфера.
другими словами, я не знаю, такой ли алгоритм:
ЧИТАТЬ ДАННЫЕ --> ДАННЫЕ ОБРАБОТКИ --> СОЗДАТЬ .ZIP
или
Читать кусок данных-> процесс процесса данных-> Записать кусок в .zip-> | ^------------------------------------------------- ------------------------------------------------------ ---------------------------
Если это так, какой размер буфера является лучшим?
Обновлять:
Я протестировал этот код, изменив размер буфера с 1024 на 64 и заархивировав те же файлы:при размере 1024 байта файл результатов размером 80 КБ был на 3 байта меньше, чем при буфере размером 64 байта.Какой размер буфера лучше всего подходит для создания наименьшего ZIP-файла в кратчайшие сроки?
Решение
Короткий ответ:Я бы выбрал что-то вроде 16 тыс.
Длинный ответ:
ZIP использует алгоритм DEFLATE для сжатия (http://en.wikipedia.org/wiki/DEFLATE).Deflate — это аромат Зива Лемпеля Уэлча (поищите в Википедии LZW).DEFLATE использует кодирование LZ77 и Хаффмана.
Это словарное сжатие, и, насколько я знаю, с точки зрения алгоритма размер буфера, используемый при подаче данных в дефлятор, почти не должен иметь никакого влияния.Наибольшее влияние на LZ77 оказывают размер словаря и скользящее окно, которые в вашем примере не контролируются размером буфера.
Я думаю, вы можете поэкспериментировать с разными размерами буфера, если хотите, и построить график, но я уверен, что вы не увидите существенных изменений в степени сжатия (3/80000 = 0,00375%).
Наибольшее влияние размер буфера оказывает на скорость из-за объема служебного кода, который выполняется при вызовах FileInputStream.read и zos.write.С этой точки зрения вам следует учитывать, что вы получаете и что тратите.
При увеличении размера с 1 байта до 1024 байт вы теряете 1023 байта (теоретически) и получаете сокращение времени накладных расходов в методах .read и .write примерно на 1024 байта.Однако при увеличении с 1 тыс. до 64 тыс. вы тратите 63 тыс., что снижает накладные расходы в 64 раза.
Так что это приводит к убывающей отдаче, поэтому я бы выбрал что-то посередине (скажем, 16 тысяч) и придерживался этого.
Другие советы
Зависит от вашего оборудования (скорости диска и времени поиска файлов).Я бы сказал, что если вы не заинтересованы в том, чтобы выжимать последнюю каплю производительности, выберите любой размер между 4К и 64К.Поскольку это недолговечный объект, его в любом случае соберут быстро.