先上正确方法:

  正确方式应该为,先创建一个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. spring学习(01)之IOC

    spring学习(01)之IOC IOC:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创 ...

  2. 【JMeter】【接口测试】csv参数化,数据驱动,自动化测试

    csv参数化,数据驱动   首先我们要有一个接口测试用例存放的地方,我们这里用EXCEL模板管理,里面包含用例编号.入参.优先级.请求方式.url等等. 1:新建一个txt文件,命名为sjqd,后缀名 ...

  3. Hadoop 尝试

    一. 使用环境Ubuntu 安装Hadoop需要的软件 命令: $ sudo apt-get install ssh $ sudo apt-get install rsync 提示错误: 错误原因: ...

  4. SQL语法集合

    查询 select   *   from table limit 0,10     取0位置后面的10条记录 limit   0     表示从第一条记录开始   起始位置从0开始 10    表示取 ...

  5. 学习Shell(二)变量

    如何给shell脚本传入参数 1.执行“vi test.sh”创建一个新的shell脚本. vi test.sh 2.脚本test.sh的内容如下: #!/bin/sh name=$ echo &qu ...

  6. PHP策略模式2

    <?php /** PHP 策略模式 * 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. * 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因 ...

  7. 算法笔记-PHP实现队列的操作

    [队列]先进者先出,这就是典型的“队列”.         最基本的两个操作:入队enqueue(),放一个数据到队列尾部:出队dequeue(),从队列头部取一个元素.队列可以用数组或者链表实现,用 ...

  8. IOT-web替换某一个前台版本

    比如 替换endpoint 1,首先改写 package.json文件,记得去掉^,改写成某一个版本 2.删除相应的内容 3.执行 npm install 4.最后 build

  9. (转)以太坊 钱包 创建 导入 Keystore

    最近闲来无事 研究了下以太坊钱包 下边分享下 准备工作 : 需要用到的加密:BIP32 BIP39 BIP44 SCRYPT 加密算法 githab地址 https://github.com/Nova ...

  10. Python 全栈开发七 面向对象

    一.编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式 ...