在创建压缩文件之前,如何估计java中的压缩文件大小
我有一个要求,其中我必须从可用文件列表创建一个zip文件。这些文件有不同的类型,如txt、pdf、xml等。我正在使用java util类来完成这项工作 这里的要求是保持最大5 mb的文件大小。我应该根据时间戳从列表中选择文件,将文件添加到zip,直到zip文件大小达到5MB。我应该跳过剩下的文件 请让我知道,在java中是否有一种方法可以让我在不创建实际文件的情况下提前估计zip文件的大小在创建压缩文件之前,如何估计java中的压缩文件大小,java,zip,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
我曾经在一个已知输入类型的项目上这样做过一次。我们知道,一般来说,我们的数据压缩在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建议的压缩比。再次感谢大家