zoukankan      html  css  js  c++  java
  • 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文件放在两个不同的文件夹下面。这样就不会始终对同一个zip文件又读又写了。

    此外,我还在windows平台上进行了测试。发现一个很诡异的现象。在windows上文件能够正常下载,且不会出现磁盘容量爆棚的情况。但是:

    1)新打包的b.zip里面还有一个b.zip。

    2)外层的b.zip可以正常解压,里层的b.zip也可以解压和查看。但是里层的b.zip解压时会报文件末端错误。

    3)里层的b.zip还有一个b.zip,暂且叫做里里层b.zip。这个里里层b.zip就完全打不开了。

    4)用资源管理器查看tomcat所掌握的资源句柄,仍旧包括这个最外层的b.zip。也就是即便client完成了下载,服务端也没有释放这个资源。

    可以说,windows遇到了和linux平台一样的问题。但是可能因为windows操作系统的文件系统具体细节的处理方式不同,导致出现了最后这样一个相对诡异的结果。

  • 相关阅读:
    何谓算法
    大规模Web服务开发技术
    什么是依赖,什么是抽象
    智能Web算法
    算法评测
    好代码、坏代码之四
    SVN server setup 1
    Python正则表达式操作指南(re使用)(转)
    rpm package installation
    mysql install error:Make had returned bad status, install seems impossible
  • 原文地址:https://www.cnblogs.com/ShaneZhang/p/5972803.html
Copyright © 2011-2022 走看看