JAVA实现zip压缩需要注意的问题

近来对院社二维码平台进行2.0升级改造。于昨日踩到一个巨坑。特此记录。。。

需求源于院社编辑在批量下载二维码的时候,系统后台需要对所要下载的二维码进行重命名和zip打包压缩。

系统测试的时候发现:首次请求批量下载时,也即压缩文件还未生成时,后台可以正常压缩文件并提供下载。但是第二次请求批量下载时,网页一直无反应。。。

尝试了几次后仍旧没反应。只好查看tomcat日志,惊奇的发现日志只写了一半,后半部分丢失(第一次遇到这种情况)==|||

不过老天爷保佑,写入的一部分显示:No space left device.

我擦!硬盘满了?昨天还有68%的余量。今天就没了?

迅速df du命令走起。du显示并没有占满。但是df显示已经100%。这是搞毛。。

google一下,发现du df显示结果不一样的原因可能是有文件句柄没有释放,文件仍旧被进程占用。df统计的是硬盘实际占用,而du并不包括已经标记删除却仍旧被进程占用,实际上并未物理删除的文件。(文件物理删除和标识为deleted不是一个概念)

接着调用lsof | grep deleted查看文件占用情况。。果然那几个zip文件size已经突破天际了。。

看来是java对zip文件打包时出错了。陷入了死循环???

由于zip打包源码是同事提供的,并没有深入了解。不得不扒开package,查看到底是个啥子逻辑。

经过一番折腾。终于发现问题。

举个例子:

a文件下有1.jpg 2.jpg两个文件

在第一次请求批量下载时,生成了b.zip文件。

如此a文件夹下就有了1.jpg 2.jpg b.zip文件了

根据源码逻辑,首先会对a文件夹进行遍历搜索,然后将每个文件逐个加入zip文件中。

那么,第二次请求时,从表面上看,可能会粗略的以为b.zip会被覆盖掉,替换成新b.zip,里面包括1.jpg 2.jpg 和旧的b.zip。

大错特错!

文件在进行写操作时,始终是对同一个b.zip在操作!

分解一下过程。首先在遍历a文件夹得到三个文件名的列表:1 2 b

创建新b时,旧b文件会被删除,但是b这个文件名仍旧保留在上面的文件列表中。

接下来,添加1到新b,添加2到新b。

在添加旧B的时候,实则在对新B操作!!如果从文件读写指针的角度来看,如下图所示

read              write

1      2      (12)

可以看到,由于是在对同一个文件操作,read指针永远不可能赶上write,也即EOF,那么这个写就永无止境。

所以解决bug的方法是:把要打包的文件和目标zip文件放在两个不同的文件夹下面。

就酱~

时间: 2024-09-29 04:24:05

JAVA实现zip压缩需要注意的问题的相关文章

java基础---->Zip压缩的使用(转)

java中提供了对压缩格式的数据流的读写.它们封装到现成的IO 类中,以提供压缩功能.下面我们开始java中压缩文件的使用. 目录导航: 关于压缩的简要说明 GZIP压缩文件的使用 ZIP压缩文件的使用 GZIP与ZIP压缩的比较 友情链接 关于压缩的简要说明 一. Java中有着压缩的类: CheckedInputStream GetCheckSum()为任何InputStream 产生校验和(不仅是解压) CheckedOutputStream GetCheckSum()为任何OutputS

Java使用Zip压缩文件或整个目录

1.压缩文件或整个目录 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.zip.ZipEntry

java.util.zip压缩打包文件总结二: ZIP解压技术

一.简述 解压技术和压缩技术正好相反,解压技术要用到的类:由ZipInputStream通过read方法对数据解压,同时需要通过CheckedInputStream设置冗余校验码,如: CheckedInputStream cis = new CheckedInputStream(new FileInputStream( srcFile), new CRC32()); ZipInputStream zis = new ZipInputStream(cis); 需要注意的是,在构建解压文件时,需要

用java实现zip压缩

本来是写到spaces live上的,可是代码的显示效果确实不怎么好看.在javaeye上试了试代码显示的顺眼多了. 今天写了个用java压缩的功能,可以实现对文件和目录的压缩. 由于java.util.zip.ZipOutputStream有中文乱码问题,所以采用org.apache.tools.zip.ZipOutputStream. 以下是代码: Java代码   package net.szh.zip; import java.io.BufferedInputStream; import

Java.util.zip 压缩与解压缩工具类

Java.util.zip 提供用于读写标准 ZIP 和 GZIP 文件格式的类. 还包括使用 DEFLATE 压缩算法(用于 ZIP 和 GZIP 文件格式)对数据进行压缩和解压缩的类. 依赖 Jdk 编写该工具类,不依赖任何第三方 jar,随用随取,实现功能大体如下: 1.目录级别递归压缩与解压缩 zip: 2.单文件压缩和解压缩 zip : import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipIn

java.util.zip压缩打包文件总结一:压缩文件及文件下面的文件夹

一.简述 zip用于压缩和解压文件.使用到的类有:ZipEntry  ZipOutputStream 二.具体实现代码 package com.joyplus.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.

java实现zip压缩文件

在网上找到这几种方法,感觉不错,收集起来,方便大家使用 jdk自带的包java.util.zip.ZipOutputStream,不足之处,文件(夹)名称带中文时,出现乱码问题,实现代码如下 /** * 功能:把 sourceDir 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件 * @param sourceDir 如果是目录,eg:D:\\MyEclipse\\first\\testFile,则压缩目录下所有文件: * 如果是文件,eg:D:\\MyEclipse\\fi

java 解压缩zip 压缩zip

1.解压缩 package zuo.file.zip.unzip; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.util.zip.ZipEntry; imp

java I/O解析 及java.util.zip压缩

1.Java I/O框架采用装饰器模式,可按照读写方式分为字节流和字符流,二者根据数据源的不同都封装了不同的类(ByteArray.String.File.Pipe等),FilterInputStream.FilterOutputStream是用来提供装饰器类接口以控制特定输入流和输出流的两个类.字节流和字符流之间可以通过InputStreamReader和OutPutStreamWriter相互转换. 2.常用案例 import java.io.BufferedReader; import j