在创建压缩文件之前,如何估计java中的压缩文件大小

在创建压缩文件之前,如何估计java中的压缩文件大小,java,zip,Java,Zip,我有一个要求,其中我必须从可用文件列表创建一个zip文件。这些文件有不同的类型,如txt、pdf、xml等。我正在使用java util类来完成这项工作 这里的要求是保持最大5 mb的文件大小。我应该根据时间戳从列表中选择文件,将文件添加到zip,直到zip文件大小达到5MB。我应该跳过剩下的文件 请让我知道,在java中是否有一种方法可以让我在不创建实际文件的情况下提前估计zip文件的大小 或者有其他方法来处理这个问题吗?我不认为有任何方法来估计将创建的拉链的大小,因为拉链是作为流处理的。此外

我有一个要求,其中我必须从可用文件列表创建一个zip文件。这些文件有不同的类型,如txt、pdf、xml等。我正在使用java util类来完成这项工作

这里的要求是保持最大5 mb的文件大小。我应该根据时间戳从列表中选择文件,将文件添加到zip,直到zip文件大小达到5MB。我应该跳过剩下的文件

请让我知道,在java中是否有一种方法可以让我在不创建实际文件的情况下提前估计zip文件的大小


或者有其他方法来处理这个问题吗?我不认为有任何方法来估计将创建的拉链的大小,因为拉链是作为流处理的。此外,从技术上讲,除非您实际压缩所创建的压缩格式,否则无法预测其大小。

将ZipOutputStream包装成一个个性化的输出流,在这里命名为YourOutputStream

  • YourOutputStream的构造函数将创建另一个(zos2)来封装新的(baos)
    public YourOutputStream(zipoutStream zos,int-maxSizeInBytes)
  • 当你想用你的OutputStream写一个文件时,它会先在zos2上写它
    public void writeFile(文件)抛出ZipFileFullException

    public void writeFile(字符串路径)抛出ZipFileFullException

    等等
  • 如果在
    maxSizeInBytes下
    • 用zos1编写文件
  • 否则
    • 关闭zos1、baos、zos2并抛出异常。对于异常,我想不出一个已经存在的异常,如果有,就使用它,否则创建自己的IOException ZipFileFullException
你需要两个ZipoutStream,一个写在你的驱动器上,一个检查你的内容是否超过5MB

编辑:事实上我查过


我曾经在一个已知输入类型的项目上这样做过一次。我们知道,一般来说,我们的数据压缩在5:1左右(都是文本)。所以,我会检查文件大小并除以5

在本例中,这样做的目的是检查文件是否可能小于某个大小。我们只需要一个粗略的估计

综上所述,我注意到像7zip这样的zip应用程序将创建一个特定大小的zip文件(如CD),然后在达到极限后将zip拆分为一个新文件。你可以看看源代码。我以前在代码中实际使用过该应用程序的命令行版本。他们有一个图书馆,你也可以使用。但不确定它与Java的集成程度


不管它值多少钱,我还使用了一个名为SharpZipLib的库。非常好。我想知道它是否有Java端口。

+1对于Colin Herbert:逐个添加文件,或者备份上一步,或者删除最后一个文件(如果归档文件太大)。我只想补充一些细节:

预测太不可靠了。例如,PDF可以包含未压缩的文本,压缩到原始文本的30%,或者包含已压缩的文本和图像,压缩到80%。您需要检查整个PDF的可压缩性,基本上必须对其进行压缩

您可以尝试统计预测,但这可以减少失败尝试的次数,但您仍必须实施上述建议。首先使用更简单的实现,看看是否足够


或者,单独压缩文件,然后选择绑定在一起不会超过5 MB的文件。如果解包也是自动化的,那么可以将zip文件绑定到单个未压缩的zip文件中

也许您可以每次添加一个文件,直到达到5MB限制,然后丢弃最后一个文件。像@Gopi,我认为在不压缩文件的情况下,没有任何方法可以估计它


当然,文件大小不会增加(或者可能会增加一点,因为zip头?),所以至少您有一个“最坏情况”估计。

只是想分享一下我们是如何实现手动方式的

            int maxSizeForAllFiles = 70000; // Read from property
        int sizePerFile = 22000; // Red from property
        /**
         * Iterate all attachment list to verify if ZIP is required
         */
        for (String attachFile : inputAttachmentList) {
            File file = new File(attachFile);
            totalFileSize += file.length();
            /**
             * if ZIP required ??? based on the size
             */
            if (file.length() >= sizePerFile) {
                toBeZipped = true;
                logger.info("File: "
                            + attachFile
                                + " Size: "
                                + file.length()
                                + " File required to be zipped, MAX allowed per file: "
                                + sizePerFile);
                break;
            }
        }
        /**
         * Check if all attachments put together cross MAX_SIZE_FOR_ALL_FILES
         */
        if (totalFileSize >= maxSizeForAllFiles) {
            toBeZipped = true;
        }
        if (toBeZipped) {
            // Zip Here iterating all attachments
        }

有一个更好的选择。创建一个虚拟
LengthOutputStream
,它只计算写入的字节数:

public class LengthOutputStream extends OutputStream {

    private long length = 0L;

    @Override
    public void write(int b) throws IOException {
        length++;
    }

    public long getLength() {
        return length;
    }
}
您只需将
长度输出流
连接到
zipoutput流

public static long sizeOfZippedDirectory(File dir) throws FileNotFoundException, IOException {
        try (LengthOutputStream sos = new LengthOutputStream();
            ZipOutputStream zos = new ZipOutputStream(sos);) {
            ... // Add ZIP entries to the stream
            return sos.getLength();
        }
    }

LengthOutputStream
对象统计压缩流的字节数,但不存储任何内容,因此没有文件大小限制。此方法提供了准确的大小估计,但速度几乎与创建ZIP文件一样慢。

如果这真的不起作用,您可能会有一个超过5MB的文件,其中只包含“aaaa…”,它将被压缩到足以容纳ZIP。感谢您的帮助。因为我只需要大致的大小,并且能够找出我们使用的大多数文件类型的压缩比,所以我使用了Nate建议的压缩比。再次感谢大家