先上正确方法:

  正确方式应该为,先创建一个ZipFile,然后对其entries做遍历,每一个entry其实就是一个文件或者文件夹,检测到文件夹的时候创建文件夹,其他情况创建文件,其中使用zipFile.getInputStream(entry)可以获得当前文件的输入流(注意是文件的输入流不是压缩文件的输入流)。然后把它写到writer里就可以了。嘛,明明很简单的。下面是一个例子,读取GBK格式的压缩包,压缩包中的文件编码也为GBK格式(就是在windows下写的文件并打包的情况),输出为UTF8的解压(跨平台使用)。

  def decompressZip(source: File, dest: String, sourceCharacters: String = "GBK", destCharacters: String = "UTF-8") = {
if (source.exists) {
var os: OutputStream = null
var inputStream: InputStreamReader = null
var outWriter: OutputStreamWriter = null
val zipFile = new ZipFile(source, sourceCharacters)
var entries = zipFile.getEntries entries.foreach(entry =>
if (entry.isDirectory())
new File(dest + entry.getName).mkdirs()
else if (entry != null) {
try{
val name = entry.getName
val path = dest + name
var content = new Array[Char](entry.getSize.toInt)
inputStream = new InputStreamReader(zipFile.getInputStream(entry), sourceCharacters)
println(inputStream.read(content))
val entryFile = new File(path)
checkFileParent(entryFile)
os = new FileOutputStream(entryFile)
outWriter = new OutputStreamWriter(os, destCharacters);
outWriter.write(new String(content))
} catch {
case e: Throwable => e.printStackTrace()
}finally{
if (os != null){
os.flush
os.close
}
if (outWriter != null){
outWriter.flush
outWriter.close
}
if (inputStream != null) inputStream.close
}
})
zipFile.close
}
}

  错误示范:

  不知道为什么,网上很多教程都是使用ZipArchiveInputStream来进行解压,然而:

  The ZipFile class is preferred when reading from files as ZipArchiveInputStream is limited by not being able to read the central directory header before returning entries. In particular ZipArchiveInputStream

  • may return entries that are not part of the central directory at all and shouldn't be considered part of the archive.
  • may return several entries with the same name.
  • will not return internal or external attributes.
  • may return incomplete extra field data.
  • may return unknown sizes and CRC values for entries until the next entry has been reached if the archive uses the data descriptor feature.

  在commons-compress的1.3版本就开始建议使用ZipFile了。

  我个人而言,尝试过ZipArchiveInputStream之后发现一个问题,ZipArchiveInputStream创建方式很麻烦,需要指定一个InputStream,而这个方法在API文档中是这么写的

Constructors
Constructor and Description
ZipArchiveInputStream(InputStream inputStream)

Create an instance using UTF-8 encoding
ZipArchiveInputStream(InputStream inputStream, String encoding)

Create an instance using the specified encoding
ZipArchiveInputStream(InputStream inputStream, String encoding, boolean useUnicodeExtraFields)

Create an instance using the specified encoding
ZipArchiveInputStream(InputStream inputStream, String encoding, boolean useUnicodeExtraFields, boolean allowStoredEntriesWithDataDescriptor)

Create an instance using the specified encoding

  Parameters:inputStream - the stream to wrap

  这个构造方法没有指明这个inputStream参数是什么东西,照网上的方法试了试,使用:  

val zipFile = new ZipFile(source, sourceCharacters)
var entries = zipFile.getEntries
entries.foreach(entry =>
if (entry != null) {
try{
val name = entry.getName
val path = dest + name
var content = new Array[Char](entry.getSize.toInt)
zais = new ZipArchiveInputStream(zipFile.getInputStream(entry))
val entryFile = new File(path)
checkFileParent(entryFile)
os = new FileOutputStream(entryFile)
IOUtils.copy(zais, os)
………………

  读出来的数据是空,使用zais.read读出Array[Byte]并把它转化为字符串发现是空白符字符串,直接输出Array[Byte]发现都是0。后来看文档大概知道是什么原因,这个ZipArchiveInputStream读取的应该是Zip文件,然而zipFile.geiInputStream返回的是解压完的文件的输入流,所以才会出现这个问题,试了试commons-compress spark依赖12年出的1.4版本和最新的1.14版本这种方法都是错的,所以我怀疑他们12年之后转的那些博客并没有经过自己使用和测试就转发了。这个ZipFile和ZipArchiveInputStream混用总觉得怪怪的。。。

使用commons-compress解压GBK格式winzip文件到UTF8,以及错误使用ZipArchiveInputStream读出来数据全是空的解决办法的更多相关文章

  1. JAVA解压.Z及.ZIP文件

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress --> <dependency ...

  2. 文件压缩、解压工具类。文件压缩格式为zip

    package com.JUtils.file; import java.io.BufferedOutputStream; import java.io.File; import java.io.Fi ...

  3. 解压gzip格式文件(包括网页)

    先上源码 参数说名: - source :gzip格式流内容. - len: gzip流长度 - dest: 解压后字符流指针 - gzip: 压缩标志,非0时解压gzip格式,否则按照zip解压 说 ...

  4. C#使用Expand、Shell32解压Cab、XSN文件

    前言: 需要解压InfoPath表单的xsn文件,在项目中以前使用的是Expand命令行解压,都没有出过问题,近段时间项目中突然报错解压失败,通过分析解压操作得出结论: 1.正常正常情况下,expan ...

  5. tar 解压某个指定的文件或者文件夹

    1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使用#tar -tf 压缩包名称,可以查看压缩包内容 2.解压某个文件 tar -zxvf zabbix.tar ...

  6. 如何解压POSIX tar archive文件

    下载了一个xxx.gz的文件,使用x xxx.gz(zsh的x插件,十分之好用,再也不用担心tar后面该加哪些参数了)的命令解压,然后出现了一个文件,本以为解压后是一个文件夹:然后一脸蒙逼~ 突然又想 ...

  7. 解压.zip,.tar.gz文件到指定目录,重命名文件

    1.解压文件到指定目录 /** * 解压文件到指定目录 * zipFile:要解压的文件 * descDir:解压到哪个文件 * */ @SuppressWarnings("rawtypes ...

  8. tar解压某个目录 tar解压某个指定的文件或者文件夹

    tar解压某个目录 tar解压某个指定的文件或者文件夹 发布时间:2017-05-30 来源:服务器之家   1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使 ...

  9. Python:将utf-8格式的文件转换成gbk格式的文件

    需求:将utf-8格式的文件转换成gbk格式的文件 实现代码如下: def ReadFile(filePath,encoding="utf-8"): with codecs.ope ...

随机推荐

  1. 【托业】【新托业TOEIC新题型真题】学习笔记7-题库二->P1~4

    P1: 1. shopping cart 购物车 stock the shelves 补货 examining the vegetables 挑选蔬菜 4.admire some paintings ...

  2. 防止SQL注入的6个要点

    SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.防止SQL注入,我们可以从以下6个要点来进行: 1.永远不要信任用户的输入 ...

  3. 如何将finecms链接URL中的list和show去掉

    finecms上手还算比较快吧,对seo关注的朋友会想着将它的url改造了,里面多了-list-和-show-,可以直接去掉,下面就随着ytkah一起来进行设置吧. 首先到后台的url规则,将列表和列 ...

  4. 递归与非递归打印乘法口诀表--Scala(指令式、函数式思维练习)

    object Test extends App { def printMultiTable() { var i = 1 while (i < 10) { var j = 1 while (j & ...

  5. C++中关于new和delete的使用

    1.创建动态数组 数组类型的变量有三个重要的限制:数组长度固定不变,在编译时必须知道它的长度,数组只在定义它的块语句中存在.对于动态分配的数组,虽然长度是固定的,但是动态分配的数组不必在编译时知道其长 ...

  6. 万恶之源 - Python生成器

    生成器 首先我们来看看什么是个生成器,生成器本质就是迭代器 在python中有三种方式来获取生成器 1.通过生成器函数 2.通过各种推到式来实现生成器 3.通过数据的转换也可以获取生成器 首先,我们先 ...

  7. Python 全栈开发十 socket网络编程

    一.客户端(client)服务端(sever)架构 在计算机中有很多常见的C/S架构,例如我们的浏览器是客户端.而百度网站和其他的网站就是服务端:视频软件是客户端,提供视频的腾讯.优酷.爱奇艺就是服务 ...

  8. git 不区分文件大小写的处理

  9. WinRAR 5.40 & 4.20 & 3.93 的注册码 - rarreg.key

    把下面的数据复制到“记事本”中,用文件名“rarreg.key”命名该文件,保存到WinRAR安装文件夹即完成注册. 以下4个Key随便选一个复制都可以. WinRAR 5.40 版Key,复制箭头中 ...

  10. vue中连续点击3次且时间间隔不超过3秒,才显示div(刚开始隐藏的)

    num:0,//点击次数timer0:'',//第一次点击的时间timer4:'',//第四次点击的时间centerDialogVisible: false // 连续4次点击显示模态框 change ...