一、JDK内置操作Zip文件
其实,在JDK中已经存在操作ZIP的工具类:ZipInputStream。

基本使用:

public static Map<String, String> readZipFile(String file) throws Exception {
Map<String, String> resultMap = new HashMap<String, String>();
Charset gbk = Charset.forName("GBK");
ZipFile zf = new ZipFile(file, gbk); // 此处可以用无Charset的构造函数,但是即使是设置为GBK也是处理不了中文的,后面会再说
InputStream in = new BufferedInputStream(new FileInputStream(file));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry ze;

while ((ze = zin.getNextEntry()) != null) {
if (ze.isDirectory()) {
} else {
long size = ze.getSize(); // 文件的大小
String name = ze.getName(); // 获取文件名称
// 具体对其中每个文件的操作和获取信息,可以参考JDK API
if (size > 0) {
InputStream inputStream = zf.getInputStream(ze); // 拿到文件流
// …… 业务逻辑
}
}
}
zin.closeEntry();

return resultMap;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
更多的操作可以参考其他人的总结,本文的重点在于描述JDK自带zip操作API的不便之处,从而引出Zip4J。

JDK自带ZIP API有个非常重大的问题:不支持ZIP中目录中的中文。如下异常:

java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(Unknown Source)
at java.util.zip.ZipInputStream.readLOC(Unknown Source)
at java.util.zip.ZipInputStream.getNextEntry(Unknown Source)
at com.mskj.test.md5.BigFileMD5.readZipFile(BigFileMD5.java:131)
at com.mskj.test.md5.BigFileMD5.checkFileMD5(BigFileMD5.java:42)
at com.mskj.test.TestMain.main(TestMain.java:12)
1
2
3
4
5
6
7
我的ZIP中目录:“Test\Test-01\Te\你好\……”,当然导致该异常的原因不只是中文的问题,但是大部分情况下都是。对于JDK自带的ZIP API还有一些其他问题,比如操作解压和压缩API接口不方便(带有密码ZIP)等。当然,网上有许多人说是已经可以解决中文的问题,但是比较麻烦,并不是每次都能够成功,我本地也有尝试过。

在我们的项目中,通过不断的比较,最终还是选择了ZIP4J。

二、ZIP4J
官网:http://www.lingala.net/zip4j/

zip4j默认采用的是UTF-8编码,所以本身支持中文(但是,个人建议还是在读取zip文件后,立即设置字符集),同时也支持密码,而且支持多种压缩算法,可以说功能强大,但使用起来却非常简单,当然,如果有其他需求,需要自己从官网上看API。如果你百度或者谷歌ZIP4J的用法,会有许多好的博客和教程,再此不再赘述。
例如:
https://blog.csdn.net/ditto_zhou/article/details/82977395
https://www.cnblogs.com/622698abc/p/3389855.html
https://rensanning.iteye.com/blog/1836727
……

我想结合一下我项目中需求以及网上许多同仁的问题(不解压zip文件,直接通过InputStream的形式读取其中的文件信息),说一个简单的应用:不解压ZIP文件的前提下,直接利用流(InuptStream)形式读取其中的文件,并读取文件的MD5值。

类似于JDK自带ZipInputStream的形式读取zip文件,由于ZIP4J的ZipInputStream不具备ZipInputStream.getNextEntry()),所以,在ZIP4J中只能通过FileHeader来进行循环。而且,JDK自带API中获取ZIP其中的文件流InputStream时,需要:

ZipFile zf = new ZipFile(file);
InputStream inputStream = zf.getInputStream(ZipEntry);
1
2
所以,对应ZIP4J就只能ZipInputStream(该类时InputStream的子类)。

具体代码如下:

import java.util.List;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.io.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;

public class ZIP4JUtils {
/**
* @param file
* @throws Exception
*/
public static void readZipFileMD5ByZip4J(String file) throws Exception {
file.replaceAll("\\\\", "/");
ZipFile zFile = new ZipFile(file);
// 此处最好立即设置字符集
zFile.setFileNameCharset("GBK");
if (!zFile.isValidZipFile()) {
return ;
}

// 获取ZIP中所有文件的FileHeader,以便后面对zip中文件进行遍历
List<FileHeader> list = zFile.getFileHeaders();
// 此时list的size包括:文件夹、子文件夹、文件的个数
System.out.println(list.size());
// 遍历其中的文件
for (FileHeader fileHeader : list) {
String fileName = fileHeader.getFileName();
// fileName会将目录单独读出来,而且带有路径分割符
if (fileName.endsWith("/") || fileName.endsWith("\\\\") || fileName.endsWith("\\")) {
System.out.println(fileName + " 这是一个文件夹。");
continue;
}else {
ZipInputStream inputStream = zFile.getInputStream(fileHeader);
String Md5String = BigFileMD5.getStreamMD5(inputStream);
System.out.println(fileName + " 这是一个文件,该文件的MD5值:" + Md5String);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
其中计算MD5值的类如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.Hex;

public class BigFileMD5 {
static MessageDigest MD5 = null;
static List<File> list = new ArrayList<File>();
static{
try{
MD5 = MessageDigest.getInstance("MD5");
}catch(NoSuchAlgorithmException e){
e.printStackTrace();
}
}

/**
* 对一个文件获取md5值
* @return md5串
*/
public static String getStreamMD5(InputStream fileInputStream) {
try {
byte[] buffer = new byte[8192];
int length;
while ((length = fileInputStream.read(buffer)) != -1) {
MD5.update(buffer, 0, length);
}

return new String(Hex.encodeHex(MD5.digest()));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if (fileInputStream != null)
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 对一个文件获取md5值
* @return md5串
*/
public static String getMD5(File file) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[8192];
int length;
while ((length = fileInputStream.read(buffer)) != -1) {
MD5.update(buffer, 0, length);
}

return new String(Hex.encodeHex(MD5.digest()));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if (fileInputStream != null)
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
输出结果:

Test-01/ 这是一个文件夹。
Test-01/BigFielMD5.jar 这是一个文件,该文件的MD5值:db55e6677f7087754f11eaf84b2d728e
Test-01/Te/ 这是一个文件夹。
Test-01/Te/Test.txt 这是一个文件,该文件的MD5值:c6354a0eb36fac331c138eec7a4826ef
Test-01/Te/你好/ 这是一个文件夹。
Test-01/Te/你好/Hello/ 这是一个文件夹。
Test-01/Te/你好/Hello/antlr-2.7.2.jar 这是一个文件,该文件的MD5值:a73459120df5cadf75eaa98453433a01
Test-01/Te/你好/Hello/antlr-2.7.2.jar.sha1 这是一个文件,该文件的MD5值:3aa5bc052867b339a0b6ed0546f9b336
Test-01/Te/你好/Hello/antlr-2.7.2.pom 这是一个文件,该文件的MD5值:b1136da0c12ce8ffc18d00f8742256ee
Test-01/Te/你好/Hello/antlr-2.7.2.pom.sha1 这是一个文件,该文件的MD5值:ebd38323fc24c8aab361b2a7660ec666
Test-01/测试.txt 这是一个文件,该文件的MD5值:0b60aa5d9aa241ca6063495086e38e95
1
2
3
4
5
6
7
8
9
10
11
这样就实现了,Java不解压直接读取zip文件和文件内容(InputStream的形式)。

如有不对之处,还请指教!
---------------------

Java处理ZIP文件的解决方案——Zip4J(不解压直接通过InputStream形式读取其中的文件,解决中文乱码)的更多相关文章

  1. Java底层代码实现单文件读取和写入(解决中文乱码问题)

    需求: 将"E:/data/车站一次/阿坝藏族羌族自治州.csv"文件中的内容读取,写入到"E:/data//车站一次.csv". 代码: public cla ...

  2. java解压多目录Zip文件(解决中文乱码问题)--转载

    原文地址:http://zhangyongbo.iteye.com/blog/1749439 import java.io.BufferedOutputStream; import java.io.F ...

  3. java 读取文件到String(解决中文乱码)

    在改写V&View(维视)时用到了文件管理,需要从html文档读取字符串,可是一直出现中文乱码,一直解决不了.而且很是意外,我在本地运行代码时就能正常读取中文,当放到tomcat上时全是乱码, ...

  4. java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别

    这里先写几个大家容易搞混的编码设置代码: 在jsp代码中的头部往往有这两行代码 pageEncoding是jsp文件本身的编码contentType的charset是指服务器发送给客户端时的内容编码J ...

  5. java web过滤器实际应用(解决中文乱码 html标签转义功能 敏感字符过滤功能)

    转载地址:http://www.cnblogs.com/xdp-gacl/p/3952405.html 在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可 ...

  6. SSH项目web.xml文件的常用配置【struts2的过滤器、spring监听器、解决Hibernate延迟加载问题的过滤器、解决中文乱码的过滤器】

    配置web.xml(struts2的过滤器.spring监听器.解决Hibernate延迟加载问题的过滤器.解决中文乱码的过滤器) <!-- 解决中文乱码问题 --> <filter ...

  7. cocos2d-x:读取指定文件夹下的文件名称+解决中文乱码(win32下有效)

    援引:http://blog.csdn.net/zhanghefu/article/details/21284323 http://blog.csdn.net/cxf7394373/article/d ...

  8. java对 zip文件的压缩和解压(ant解决中文乱码)

    说明: 1.对于压缩的文件,当文件名称是中文时,若使用JDK API中自带的类(java.util.zip.ZipEntry; java.util.zip.ZipOutputStream;)进行压缩, ...

  9. JAVA本地读取文件,解决中文乱码问题

    JAVA本地读取文件出现中文乱码,查阅一个大神的博客做一下记录 import java.io.BufferedInputStream;import java.io.BufferedReader;imp ...

随机推荐

  1. VA市场高烧已退,逐渐降温

    本周市场国产VA报价在175元/公斤左右,较上周滑落.因前期停报的厂家均已报价,个别国产厂家报价较低,各厂家间报价价差较大,彰显不同态度.国内厂家供应依然偏紧,但较前期已缓解.中小饲料企业库存偏低,近 ...

  2. Java反射的基本应用

    反射机制,程序在运行时加载新的类,使程序更加灵活 public class HelooReflect { public static void main(String[] args) { // 获取类 ...

  3. AppCompatActivity、ActionBarActivity、FragmentActivity和Activity的区别

    package com.chy.myapplication; import android.support.v7.app.AppCompatActivity; import android.os.Bu ...

  4. Mac 中安装 Apache Ant

    1.下载Apache Ant:http://ant.apache.org/bindownload.cgi 2.解压apache-ant-1.9.6-bin.zip,把解压好的apache-ant-1. ...

  5. Masonry tableviewCell布局

    前言 说到iOS自动布局,有很多的解决办法.有的人使用xib/storyboard自动布局,也有人使用frame来适配.对于前者,笔者并不喜欢,也不支持.对于后者,更是麻烦,到处计算高度.宽度等,千万 ...

  6. 在 Ubuntu 16.04 中安装支持 CPU 和 GPU 的 Google TensorFlow 神经网络软件

    TensorFlow 是用于机器学习任务的开源软件.它的创建者 Google 希望提供一个强大的工具以帮助开发者探索和建立基于机器学习的应用,所以他们在去年作为开源项目发布了它.TensorFlow ...

  7. [USACO 2017DEC] Haybale Feast

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5142 [算法] 首先用RMQ预处理S数组的最大值 然后我们枚举右端点 , 通过二分求 ...

  8. bzoj 1014 火星人prefix —— splay+hash

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用 splay 维护字符串上不同位置的哈希值还是第一次... 具体就是每个节点作为位置 ...

  9. Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试

    ylbtech-Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试 1.返回顶部 1. Java 实例 - 字符串性能比较测试  Java 实例 以下实例演 ...

  10. maven中添加json-lib的jar包

    在maven配置文件pom.xml中添加如下配置信息: <dependency> <groupId>net.sf.json-lib</groupId> <ar ...