如何创建具有最大文件大小限制的java zip存档

时间:2012-06-19 16:01:10

标签: java zip

我需要在java中编写一个算法(对于Android应用程序)来读取包含更多文件夹的文件夹,每个文件夹包含图像和音频文件,所以结构是这样的:mainDir/categorySubfolder/myFile1.jpg

我的问题是我需要将存档的大小限制为16mb,并且在运行时,根据需要创建尽可能多的存档以包含我的主mainDir文件夹中的所有文件。

我在网上尝试了几个例子,我阅读了java文档,但是我无法理解并按照我需要的方式将它们整合在一起。有人之前做过这个或者有链接或示例吗?

我用递归方法解决了文件的读取问题,但我无法编写zip创建的逻辑。

我愿意接受建议或更好的工作实例。

3 个答案:

答案 0 :(得分:4)

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

您可以在他们的网站上找到更多示例。

答案 1 :(得分:2)

我使用下面的代码/类来分割和压缩大量/大小的文件。 我在下面测试了这个课程

  • 未压缩文件数:116
  • 总大小(未压缩):29.1 GB
  • ZIP文件大小限制(每个):3 GB [MAX_ZIP_SIZE]
  • 总尺寸(压缩):7.85 GB
  • ZIP文件数量(拆分为 MAX_ZIP_SIZE ):3

您必须将 MAX_ZIP_SIZE 的值更改为16(MB)* 1024 * 1024 = 16777216-22(zip标题大小)= 16777194
在我的代码中,MAX_ZIP_SIZE设置为3 GB(ZIP has limitation of 4GB on various things)。

  

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

}
  

我已将所有<​​em>异常消息作为字符串返回以使用它。这个   我自己的案例与项目有关。

答案 2 :(得分:1)

据我所知How to split a huge zip file into multiple volumes?只是建议到目前为止跟踪存档大小,当它接近某个任意值(应该低于你的最大值)时,它会决定开始一个新的文件。因此,对于16MB的限制,您可以将值设置为10MB并在达到此值时启动新的zip,但是如果您达到9MB并且您的下一个文件压缩到8MB,则最终会得到比您的限制更大的拉链。

该帖子中给出的代码似乎对我不起作用,因为1)它在ZipEntry创建之前得到了大小,所以它总是0和2)它没有写出任何zip :-)如果我错了 - 让我知道。

以下适用于我。为简单起见,我已将它从Wrapper中取出并将其全部放在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;
        }
}