java 读取 rar 注释_Java处理ZIP文件的解决方案——Zip4J(不解压直接通过InputStream形式读取其中的文件,解决中文乱码)...

一、JDK内置操作Zip文件

其实,在JDK中已经存在操作ZIP的工具类:ZipInputStream。

基本使用:

public static Map readZipFile(String file) throws Exception {

Map resultMap = new HashMap();

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 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 list = new ArrayList();

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的形式)。

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

---------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值