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

Мне нужно написать алгоритм в Java (для приложения Android), чтобы прочитать папку, содержащую больше папок и каждая из которых содержит изображения и аудиофайлы, поэтому структура такова: mainDir/categorySubfolder/myFile1.jpg

Моя проблема заключается в том, что мне нужно ограничить размер архива до 16 МБ, а во время выполнения создать столько архивов, сколько нужно, чтобы содержать все мои файлы из моего основного mainDir папка.

Я попробовал несколько примеров из сети, и я прочитал документацию по Java, но не могу понять и собрать все вместе так, как мне нужно. Кто-то делал это раньше или у меня есть ссылка или пример для меня?

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

Я открыт для предложений или лучшего рабочего примера.

3 ответа

Решение

zip4j - это отличная библиотека, которая может создавать многокомпонентные zip-файлы.

net.lingala.zip4j.core.ZipFile zipFile = new ZipFile("out.zip");
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
zipFile.createZipFileFromFolder("path/to/source/dir", parameters, true, maximum size);

Вы можете найти больше примеров на их веб-сайте.

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

  • количество несжатых файлов: 116
  • общий размер (без сжатия): 29,1 ГБ
  • Ограничение размера файла ZIP (каждый): 3 ГБ [MAX_ZIP_SIZE]
  • общий размер (сжатый): 7,85 ГБ
  • номер файла ZIP (разделен как MAX_ZIP_SIZE): 3

Вы должны изменить значение MAX_ZIP_SIZE на 16(МБ)*1024*1024=16777216-22(размер заголовка почтового индекса) =16777194.
В моем коде MAX_ZIP_SIZE установлен на 3 ГБ ( ZIP имеет ограничение 4 ГБ на разные вещи).

окончательный длинный MAX_ZIP_SIZE = 3221225472L; //3 ГБ

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class QDE_ZIP {

    public static String createZIP(String directoryPath, String zipFileName, String filesToZip) {
        try {
            final int BUFFER = 104857600; // 100MB
            final long MAX_ZIP_SIZE = 3221225472L; //3 GB
            long currentSize = 0;
            int zipSplitCount =0;
            String files[] = filesToZip.split(",");
            if (!directoryPath.endsWith("/")) {
                directoryPath = directoryPath + "/";
            }
            byte fileRAW[] = new byte[BUFFER];
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toUpperCase()));
            ZipEntry zipEntry;
            FileInputStream entryFile;
            for (String aFile : files) {
                zipEntry = new ZipEntry(aFile);
                if (currentSize >= MAX_ZIP_SIZE)
                {
                    zipSplitCount ++;
                    //zipOut.closeEntry();
                    zipOut.close();
                    zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toLowerCase().replace(".zip", "_"+zipSplitCount+".zip").toUpperCase()));
                    currentSize = 0;
                }
                zipOut.putNextEntry(zipEntry);
                entryFile = new FileInputStream(directoryPath + aFile);

                int count;
                while ((count = entryFile.read(fileRAW, 0, BUFFER)) != -1) {
                    zipOut.write(fileRAW, 0, count);

                    //System.out.println("number of Bytes read = " + count);
                }
                entryFile.close();
                zipOut.closeEntry();
                currentSize += zipEntry.getCompressedSize();
            }

            zipOut.close();
            //System.out.println(directory + " -" + zipFileName + " -Number of Files = " + files.length);
        } catch (FileNotFoundException e) {
            return "FileNotFoundException = " + e.getMessage();
        } catch (IOException e) {
            return "IOException = " + e.getMessage();
        } catch (Exception e) {
            return "Exception = " + e.getMessage();
        }

        return "1";
    }

}

Я вернул все сообщения об исключениях в виде строки для работы с ним. это мой собственный случай, связанный с проектом.

Насколько я вижу Как разделить огромный zip-файл на несколько томов? просто предлагает отслеживать размер архива до сих пор, и когда он приближается к какому-то произвольному значению (которое должно быть ниже вашего максимального значения), он решает начать новый файл. Таким образом, для ограничения в 16 МБ вы можете установить значение 10 МБ и начинать новый zip каждый раз, когда это будет достигнуто, но если вы достигнете 9 МБ, а ваш следующий файл уменьшится до 8 МБ, вы получите zip больше, чем ваш лимит.

Код, приведенный в этом посте, похоже, не работает для меня, потому что 1) он получил размер до того, как был создан ZipEntry, поэтому всегда было 0 и 2) он не выписывал zip:-) Если я неправильно понял - дайте мне знать.

Следующее работает для меня. Для простоты я вынул его из оболочки и просто поместил все в main(String args[]). Есть много способов улучшить этот код:-)

import java.util.zip.*;  
import java.io.*;   



    public class ChunkedZipTwo {

        static final long MAX_LIMIT=10 * 1000 * 1024; //10MB limit - hopefully this 


        public static void main(String[] args)  throws Exception {      


            String[] files = {"file1", "file2", "file3"};
            int i = 0;
            boolean needNewFile = false;
            long overallSize = 0;
            ZipOutputStream out = getOutputStream(i);
            byte[] buffer = new byte[1024];

            for (String thisFileName: files) {


                    if (overallSize > MAX_LIMIT) {
                        out.close();
                        i++;
                        out = getOutputStream(i);
                        overallSize=0;
                    }

                    FileInputStream in = new FileInputStream(thisFileName);
                    ZipEntry ze = new ZipEntry(thisFileName);
                    out.putNextEntry(ze);   
                    int len;   
                    while ((len = in.read(buffer)) > 0) {   
                        out.write(buffer, 0, len);   
                    }   
                    out.closeEntry();
                    in.close(); 
                    overallSize+=ze.getCompressedSize();




            }
            out.close();    
        }

        public static ZipOutputStream getOutputStream(int i) throws IOException {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream("bigfile" + i +".zip"));   
            out.setLevel(Deflater.DEFAULT_COMPRESSION);
            return out;
        }
}   
Другие вопросы по тегам