本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

用于大量文件的 Java zip 库

发布于2023-11-26 20:54     阅读(836)     评论(0)     点赞(0)     收藏(0)


我有超过 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 archivefolder”尝试了相同的操作,只花了 4 分钟。编辑:最近无法在 40 分钟内获得 zip。我想也许 4 分钟的拉链可能会损坏。

所以我想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 似乎都是不错的选择,让我可以选择压缩或速度最重要。

我没有测试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);
}

解决方案


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

zip如果这看起来符合您的要求,您可以从 Java 调用。许多使用命令行工具的 Maven 插件(特别是用于版本控制的插件)

顺便说一句,您可以使用 tar + bz2 等方式获得更好的压缩效果。这通过压缩整个存档而不是单独压缩每个文件来压缩更多。这意味着如果不解压缩/重新压缩整个内容,您就无法触摸它。(与 JAR/ZIP 不同,您可以在其中执行此操作)



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/685000/88f27655d17f38fa5484/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

0 0
收藏该文
已收藏

评论内容:(最多支持255个字符)