用于大量文件的Java zip库

时间:2013-11-04 07:46:05

标签: java maven zip large-files zip4j

我有超过100.000个文件,差不多有4GB。 它的html因此可以压缩70-80%。 文件范围从200 KB到几乎10 MB。

我正在开发一个将文件从xml转换为html的应用程序。 最后,应用程序将html目录存档为zip文件。

我使用了一个名为“copy-maven-plugin”的maven插件。这个插件的文档非常好,很容易使用。插件使用的存档功能默认为“ant zip”,但您可以将其更改为使用TrueZip。打开它的对面。无论如何,我试图两种方式包装mye怪物文件夹。默认的Ant zip使用43分钟,TrueZip使用38分钟。在我看来,这两种方式都很重要。

然后我在命令行中尝试使用“zip -r archive folder”,只用了4分钟。 编辑:最近未能在40分钟内获得拉链。我想也许4分钟可能会以一个腐败的拉链结束。

所以我认为在处理这么多文件时,java可能不是那么好。

有没有人知道或有过这类问题的经验?

我在考虑实现自己的东西,通过改变字节读取大小,它会有所帮助吗? 我知道你可以通过ZipInj使用ZipInputStream / ZipOutputStream来限制读取的数据块来创建/解压缩zip文件并使用你自己的缓冲区大小,但我还没有尝试过。当它像永远一样,我不能一直等待发现; - )

截至昨晚,maven在一个zipIt.sh(zip -r ...)上调用exec在合理的时间内完成工作,但我想给java带来疑问。

更新1 我测试了不同的方法(所有默认压缩级别):

    来自java的
  1. zip4j。只花了3分钟。但该文件已损坏。似乎zip4j不处理这个数量的文件。
  2. Ant zip(通过maven插件)。压缩:大约980MB。速度慢:大约40分钟
  3. 来自命令行的
  4. tar + xz。压缩:567MB。速度差:63分钟。
  5. 来自命令行的
  6. zip。压缩:981MB。速度:40分钟
  7. 来自命令行的
  8. tar + bz2。压缩:602MB。速度:13分钟
  9. 来自命令行的tar + gz。压缩:864MB。速度:5分钟
  10. java.util.zip.ZipOutputStream中。压缩:986MB。速度:炽烈的4分18秒
  11. tar + bz2和tar + gz似乎都是很好的选择,并且给我选择压缩或速度是最重要的。

    我没有测试jdk7.0 ZipOutputStream,但似乎我可能已经解决了它。我使用64KB(64 * 1024)的读缓冲区,它看起来像一个魅力。似乎我毕竟用java打了金: - )

    这是我的实施

    public static void main(String [] args) {
        String outputFile = Config.getProperty(Property.ZIP_FILE);
        String folderToAdd = Config.getProperty(Property.HTML_FOLDER);
        Zipper.zip(outputFile, folderToAdd, 64*1024);
    }
    
    private static void zip(String zipFile, String sourceDirectory, int readChunk) {
    
        ZipOutputStream out = null;
        try {
    
            //create byte buffer
            byte[] buffer = new byte[readChunk];
    
            File dirObj = new File(sourceDirectory);
            out = new ZipOutputStream(new FileOutputStream(zipFile));
            logger.info("Creating zip {} with read buffer '{}'", zipFile, readChunk);
            addDir(dirObj, out, buffer);
    
        } catch (IOException ioe) {
            logger.error("IOException :" + ioe);
        } finally {
            IOUtils.closeQuietly(out);
        }
    
    }
    
    private static void addDir(File dirObj, ZipOutputStream out, byte [] readChunk) throws IOException {
        logger.debug("Zipping folder '{}'", dirObj.getName());
        StopWatch watch = new StopWatch();
        watch.start();
    
        File[] files = dirObj.listFiles();
    
        for (File file : files != null ? files : new File[0]) {
            if (file.isDirectory()) {
                addDir(file, out, readChunk);
                continue;
            }
            FileInputStream in = null;
            try {
                in = new FileInputStream(file.getAbsolutePath());
                out.putNextEntry(new ZipEntry(file.getAbsolutePath()));
                int len;
                while ((len = in.read(readChunk)) > 0) {
                    out.write(readChunk, 0, len);
                }
    
            } finally {
                out.closeEntry();
                IOUtils.closeQuietly(in);
            }
        }
        watch.stop();
        logger.debug("Zipped folder {} in {} seconds.", dirObj.getName(), watch);
    }
    

1 个答案:

答案 0 :(得分:1)

我怀疑问题是这样的文件数量。您需要能够操作ZIP条目而无需解压缩并重新打包所有条目。这可以产生显着的差异。我预计会有10倍的差异。这可以用Java完成,但我怀疑大多数库不是为此而设计的。

如果看起来像你想做的那样,你可以从Java调用zip。许多使用命令行工具的maven插件(特别是用于版本控制的插件)

BTW你可以使用tar + bz2这样的东西获得更好的压缩效果。这通过压缩整个存档而不是单独压缩每个文件来压缩更多。这意味着如果不解压缩/重新压缩整个事物,你就无法触摸它。 (与你可能会这样做的JAR / ZIP不同)