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

时间:2010-08-26 06:05:29

标签: java zip

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

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

如果我在java中有办法可以提前估算zip文件大小而不创建实际文件,请告诉我吗?

或者还有其他方法来处理这个

7 个答案:

答案 0 :(得分:8)

将ZipOutputStream包装到个性化的OutputStream中,命名为YourOutputStream。

  • YourOutputStream的构造函数将创建另一个ZipOutputStream(zos2),它包装一个新的ByteArrayOutputStream(baos)
    public YourOutputStream(ZipOutputStream zos, int maxSizeInBytes)
  • 如果要使用YourOutputStream编写文件,它将首先在zos2上写入 public void writeFile(File file) throws ZipFileFullException
    public void writeFile(String path) throws ZipFileFullException
    等...
  • 如果baos.size()位于maxSizeInBytes
    • 将文件写入zos1
  • 否则
    • 关闭zos1,baos,zos2抛出异常。对于异常,我想不出已经存在的异常,如果有,请使用它,否则创建自己的IOException ZipFileFullException。

您需要两个ZipOutputStream,一个要写在您的驱动器上,一个用于检查您的内容是否超过5MB。

编辑:事实上,我检查了you can't remove a ZipEntry easily

http://download.oracle.com/javase/6/docs/api/java/io/ByteArrayOutputStream.html#size()

答案 1 :(得分:1)

+1 Colin Herbert:逐个添加文件,要么备份上一步,要么删除最后一个文件(如果存档很大)。我只是想补充一些细节:

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

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

我不认为有任何方法可以估算将要创建的zip的大小,因为拉链被处理为流。此外,除非您实际压缩它,否则在技术上无法预测创建的压缩格式的大小。

答案 4 :(得分:0)

我在具有已知输入类型的项目上执行了一次。我们知道一般来说我们的数据压缩大约是5:1(这是所有文本。)所以,我要检查文件大小并除以5 ......

在这种情况下,这样做的目的是检查文件是否可能低于特定大小。我们只需粗略估计。

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

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

答案 5 :(得分:0)

只想分享我们如何实施手动方式

            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
        }

答案 6 :(得分:0)

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

public class LengthOutputStream extends OutputStream {

    private long length = 0L;

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

    public long getLength() {
        return length;
    }
}

您只需将LengthOutputStreamZipOutputStream

连接即可
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文件一样慢。