1

我有超过 100.000 个文件,其中将近 4GB。它的 html 因此可以压缩 70-80%。文件范围从 200 KB 到近 10 MB。

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

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

然后我在命令行中使用“zip -r 存档文件夹”尝试了相同的操作,只用了 4 分钟。 编辑:最近无法在 40 分钟内获得拉链。我想也许 4 分钟的那个可能会以一个损坏的 zip 结尾。

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

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

我正在考虑也许实现我自己的东西并通过改变字节读取大小它会有所帮助吗?我知道您可以通过将 ZipInputStream/ZipOutputStream 与 Zip4j 一起使用来创建/解压缩 zip 文件并使用您自己的缓冲区大小来限制读取的数据块,但我没有尝试过。当它需要永远时,我不能一直等待找出答案;-)

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

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

  1. 来自java的zip4j。只用了3分钟。但文件已损坏。似乎 zip4j 不处理这么多文件。
  2. Ant zip(通过 maven 插件)。压缩:大约 980MB。慢速:约40分钟
  3. tar + xz 从命令行。压缩:567MB。速度不佳:63 分钟。
  4. 从命令行压缩。压缩:981MB。速度:40分钟
  5. tar + bz2 从命令行。压缩:602MB。速度:13分钟
  6. tar + gz 从命令行。压缩:864MB。速度:5分钟
  7. java.util.zip.ZipOutputStream。压缩:986MB。速度:炽热4分18秒

tar+bz2 和 tar+gz 似乎都是不错的选择,并为我提供了压缩或速度最重要的选项。

我没有 testet 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);
}
4

1 回答 1

1

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

zip如果这似乎符合您的要求,您可以做的是从 Java 调用。一些使用命令行工具的 maven 插件(尤其是那些用于版本控制的插件)

顺便说一句,您可以使用 tar + bz2 之类的东西获得更好的压缩效果。这通过压缩整个存档而不是单独压缩每个文件来压缩更多。这意味着你不能在不解压缩/重新压缩整个东西的情况下触摸它。(与 JAR/ZIP 不同,您可能会这样做)

于 2013-11-04T08:09:46.490 回答