我有一个要求,我必须从可用文件列表中创建一个zip文件。这些文件有不同的类型,如txt,pdf,xml等。我正在使用java util类来完成它。
此处的要求是保持最大文件大小为5 MB。我应该根据时间戳从列表中选择文件,将文件添加到zip,直到zip文件大小达到5 mb。我应该跳过剩下的文件。
如果我在java中有办法可以提前估算zip文件大小而不创建实际文件,请告诉我吗?
或者还有其他方法来处理这个
答案 0 :(得分:8)
将ZipOutputStream包装到个性化的OutputStream中,命名为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
下
您需要两个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;
}
}
您只需将LengthOutputStream
与ZipOutputStream
:
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文件一样慢。