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

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

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

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

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

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

 androidu19 июн. 2012 г., 18:06
stackoverflow.com/questions/11084823/… это был мой первоначальный пост, в котором была ошибка, которую я сейчас исправил, но теперь возникло еще 2 ... во-первых, я не могу установить размер ZipEntry, а во-вторых, когда я пытаюсь извлечь файлы, которые я получаю с ошибкой "метод сжатия не поддерживается"
 androidu19 июн. 2012 г., 18:08
также потому, что я не могу установить размер ZipEntry, моя логика не работает, поэтому он всегда создает только один архив
 Damian Leszczyński - Vash19 июн. 2012 г., 18:11
возможный дубликатHow to split a huge zip file into multiple volumes?
 matt freake19 июн. 2012 г., 18:03
Какие примеры вы пробовали из интернета? Что случилось, когда ты их попробовал?
 Puce19 июн. 2012 г., 18:10
Насколько большой полный файл почтового индекса? Может ли он храниться на диске или даже храниться в памяти?

Ответы на вопрос(3)

Решение Вопроса

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

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);

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

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

number of uncompressed files : 116 total size (uncompressed) : 29.1 GB ZIP file size limit (each) : 3 GB [MAX_ZIP_SIZE] total size (compressed) : 7.85 GB number of ZIP file (splited as MAX_ZIP_SIZE): 3

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

final long MAX_ZIP_SIZE = 3221225472L; //3 GB

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";
    }

}

I have returned all Exception Messages as String to work with it. this my own case related to project.

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

Код, приведенный в этом посте, похоже, не работает для меня, потому что 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;
        }
}   
 21 июн. 2012 г., 13:34
Нет проблем, что вы должны были изменить?
 18 мар. 2019 г., 12:52
Можете ли вы сказать мне, как будет выглядеть функция распаковки для вышеуказанного почтового индекса?
 androidu20 июн. 2012 г., 23:38
Спасибо, мне удалось с небольшими изменениями в вашем коде достичь желаемого результата! : D
 androidu20 июн. 2012 г., 15:09
Я обязательно попробую :) и да, вы правы. Я получил то же поведение из моего примера кода. Я вернусь с моими результатами: D Спасибо
 androidu21 июн. 2012 г., 14:01
Я добавил BufferedOutputStream между ZipOutputStream и FileOutputStream следующим образом: FileOutputStream dest = new FileOutputStream (_zipDirectory + & quot; /zip.part" + i + & quot; .zip & quot;); ZipOutputStream out = new ZipOutputStream (new BufferedOutputStream (dest));

Ваш ответ на вопрос