使用commons-compress解压GBK格式winzip文件到UTF8,以及错误使用ZipArchiveInputStream读出来数据全是空的解决办法
先上正确方法:
正确方式应该为,先创建一个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文档中是这么写的
| 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读出来数据全是空的解决办法的更多相关文章
- JAVA解压.Z及.ZIP文件
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress --> <dependency ...
- 文件压缩、解压工具类。文件压缩格式为zip
package com.JUtils.file; import java.io.BufferedOutputStream; import java.io.File; import java.io.Fi ...
- 解压gzip格式文件(包括网页)
先上源码 参数说名: - source :gzip格式流内容. - len: gzip流长度 - dest: 解压后字符流指针 - gzip: 压缩标志,非0时解压gzip格式,否则按照zip解压 说 ...
- C#使用Expand、Shell32解压Cab、XSN文件
前言: 需要解压InfoPath表单的xsn文件,在项目中以前使用的是Expand命令行解压,都没有出过问题,近段时间项目中突然报错解压失败,通过分析解压操作得出结论: 1.正常正常情况下,expan ...
- tar 解压某个指定的文件或者文件夹
1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使用#tar -tf 压缩包名称,可以查看压缩包内容 2.解压某个文件 tar -zxvf zabbix.tar ...
- 如何解压POSIX tar archive文件
下载了一个xxx.gz的文件,使用x xxx.gz(zsh的x插件,十分之好用,再也不用担心tar后面该加哪些参数了)的命令解压,然后出现了一个文件,本以为解压后是一个文件夹:然后一脸蒙逼~ 突然又想 ...
- 解压.zip,.tar.gz文件到指定目录,重命名文件
1.解压文件到指定目录 /** * 解压文件到指定目录 * zipFile:要解压的文件 * descDir:解压到哪个文件 * */ @SuppressWarnings("rawtypes ...
- tar解压某个目录 tar解压某个指定的文件或者文件夹
tar解压某个目录 tar解压某个指定的文件或者文件夹 发布时间:2017-05-30 来源:服务器之家 1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使 ...
- Python:将utf-8格式的文件转换成gbk格式的文件
需求:将utf-8格式的文件转换成gbk格式的文件 实现代码如下: def ReadFile(filePath,encoding="utf-8"): with codecs.ope ...
随机推荐
- spring学习(01)之IOC
spring学习(01)之IOC IOC:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创 ...
- 【JMeter】【接口测试】csv参数化,数据驱动,自动化测试
csv参数化,数据驱动 首先我们要有一个接口测试用例存放的地方,我们这里用EXCEL模板管理,里面包含用例编号.入参.优先级.请求方式.url等等. 1:新建一个txt文件,命名为sjqd,后缀名 ...
- Hadoop 尝试
一. 使用环境Ubuntu 安装Hadoop需要的软件 命令: $ sudo apt-get install ssh $ sudo apt-get install rsync 提示错误: 错误原因: ...
- SQL语法集合
查询 select * from table limit 0,10 取0位置后面的10条记录 limit 0 表示从第一条记录开始 起始位置从0开始 10 表示取 ...
- 学习Shell(二)变量
如何给shell脚本传入参数 1.执行“vi test.sh”创建一个新的shell脚本. vi test.sh 2.脚本test.sh的内容如下: #!/bin/sh name=$ echo &qu ...
- PHP策略模式2
<?php /** PHP 策略模式 * 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. * 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因 ...
- 算法笔记-PHP实现队列的操作
[队列]先进者先出,这就是典型的“队列”. 最基本的两个操作:入队enqueue(),放一个数据到队列尾部:出队dequeue(),从队列头部取一个元素.队列可以用数组或者链表实现,用 ...
- IOT-web替换某一个前台版本
比如 替换endpoint 1,首先改写 package.json文件,记得去掉^,改写成某一个版本 2.删除相应的内容 3.执行 npm install 4.最后 build
- (转)以太坊 钱包 创建 导入 Keystore
最近闲来无事 研究了下以太坊钱包 下边分享下 准备工作 : 需要用到的加密:BIP32 BIP39 BIP44 SCRYPT 加密算法 githab地址 https://github.com/Nova ...
- Python 全栈开发七 面向对象
一.编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式 ...