使用zip4j压缩,解压文件以及乱码问题处理

引言

大家好,我又来水文了,说句题外话,代码生成器前后端分离响应式主题已经支持权限管理模块生成了,感兴兴趣的朋友可以去尝试下。好了,让我们进入本次文章的主题,文件的压缩和解压在项目中还是比较常见的,比如常用的导出和导入功能,有时候就需要导出或导入为zip格式,对于压缩这类的需求我一直是使用zip4j来处理,简单实用,java中虽然有自带的处理压缩的包,但中文会乱码,apache的ant包可以解决乱码问题,但使用起来较为繁琐,zip4j则要简单很多,下面一起看一下zip4j的使用方法以及我前阵子在项目中遇到的乱码问题以及解决方法吧!

压缩

zip4j的压缩文件的方法十分简单粗暴,首先引入pom依赖:

<!-- https://mvnrepository.com/artifact/net.lingala.zip4j/zip4j -->
        <dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>1.3.2</version>
        </dependency>

下面是压缩文件的代码:

/**
* 压缩带根目录
*/
public static void zipFile(String dir, String filePath) {
		try {
			ZipFile zip = new ZipFile(filePath);
			zip.setFileNameCharset("UTF-8");
			File file = zip.getFile();
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			//为了不被原有文件干扰,保证每次重新生成
			if (file.exists()) {
				file.delete();
			}
			ZipParameters parameters = new ZipParameters();
			parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
			parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
			// 要打包的文件夹
			File currentFile = new File(dir);
			if (currentFile.isDirectory()) {
				zip.addFolder(currentFile, parameters);
			} else {
				zip.addFile(currentFile, parameters);
			}
		} catch (Exception e) {
			throw new ForbiddenException("压缩出错!!");
		}
	}
/**
* 压缩根目录内的文件,不带根目录
*/
public static void zipFileList(String dir, String filePath) {
		try {
			ZipFile zip = new ZipFile(filePath);
			zip.setFileNameCharset("UTF-8");
			File file = zip.getFile();
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			//为了不被原有文件干扰,保证每次重新生成
			if (file.exists()) {
				file.delete();
			}
			ZipParameters parameters = new ZipParameters();
			parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
			parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
			// 要打包的文件夹
			File zipfloder = new File(dir);
			File[] files = zipfloder.listFiles();
			assert files != null;
			if (files.length == 0) {
				zip.addFolder(dir, parameters);
				return;
			}
			for (File theFile : files) {
				if (theFile.isDirectory()) {
					zip.addFolder(theFile, parameters);
				}
				if (theFile.isFile()) {
					zip.addFile(theFile, parameters);
				}
			}
		} catch (Exception e) {
			throw new ForbiddenException("压缩出错!!");
		}
	}

解压及防止乱码

如上压缩代码所示,zip4j在压缩文件的时候可以指定编码类型,那么解压的时候也必须使用同样的编码类型进行解压,否则就会出现乱码现象,但用户上传的时候,如果是使用window系统压缩,编码类型为gbk,如果是使用linux或者mac压缩,那么编码类型为utf-8,这点我们是不可控的,如果想要防止解压乱码,需要得知压缩包的编码类型才可以!

我最近做的一个项目就遇到了这个问题,本来以为判断压缩包的编码类型是件简单的事情,结果网上一搜,五花八门,什么方法都有,包括读取二进制流,判断字节的值等对于压缩文件来说都是不可用的,最后到了想要修改设计的地步,让用户自行选择压缩平台,然后根据用户的选择使用对应的编码解压,这也不失为一种好的方法,只是对于用户来说多了一步选择的操作。

后来我又仔细寻找了一番,终于发现了较为靠谱的方法:使用cpdetecpor第三方工具包来判断,因为只需要判断gbk或utf-8,准确率目前可以达到百分之百,这个工具包使用了内置的探测器去探测编码,按照“谁最先返回非空的探测结果,就以该结果为准”的原则返回探测到的字符集编码,因此不保证完全正确,但经过项目的实践,可以认为完全正确。(maven仓库里没有收录这个工具包,可以在文末得到获取方式,下载安装到本地maven仓库即可)

相关的解压以及判断编码类型的代码如下:

// 解压加密的压缩文件
	public static void unZip(File zipFile, String dest, String pwd) {
		try {
			// 首先创建ZipFile指向磁盘上的.zip文件
			ZipFile zFile = new ZipFile(zipFile);
			String charset = getCharset(zipFile);
			if (charset == null) {
				throw new ForbiddenException("文件不合法,可能已经被损坏!请重新打包尝试!");
			}
			zFile.setFileNameCharset(charset);
			// 验证.zip文件是否合法,包括文件是否存在、是否为zip文件、是否被损坏等
			if (!zFile.isValidZipFile()) {
				throw new ForbiddenException("文件不合法,可能已经被损坏!请重新打包尝试!");
			}
			// 解压目录
			File destDir = new File(dest);
			if (destDir.isDirectory() && !destDir.exists()) {
				destDir.mkdir();
			}
			if (zFile.isEncrypted()) {
				// 设置密码
				zFile.setPassword(pwd.toCharArray());
			}
			zFile.extractAll(dest);
		} catch (ZipException e) {
			throw new ForbiddenException("解析压缩文件过程中出现错误!!");
		}
	}


	private static String getCharset(File file) {
		/*
		 * detector是探测器,它把探测任务交给具体的探测实现类的实例完成。
		 * cpDetector内置了一些常用的探测实现类,这些探测实现类的实例可以通过add方法 加进来,如ParsingDetector、
		 * JChardetFacade、ASCIIDetector、UnicodeDetector。
		 * detector按照“谁最先返回非空的探测结果,就以该结果为准”的原则返回探测到的
		 * 字符集编码。使用需要用到三个第三方JAR包:antlr.jar、chardet.jar和cpdetector.jar
		 * cpDetector是基于统计学原理的,不保证完全正确。
		 */
		CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
		/*
		 * ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于
		 * 指示是否显示探测过程的详细信息,为false不显示。
		 */
		detector.add(new ParsingDetector(false));
		/*
		 * JChardetFacade封装了由Mozilla组织提供的JChardet,它可以完成大多数文件的编码
		 * 测定。所以,一般有了这个探测器就可满足大多数项目的要求,如果你还不放心,可以
		 * 再多加几个探测器,比如下面的ASCIIDetector、UnicodeDetector等。
		 */
		detector.add(JChardetFacade.getInstance());
		// ASCIIDetector用于ASCII编码测定
		detector.add(ASCIIDetector.getInstance());
		// UnicodeDetector用于Unicode家族编码的测定
		detector.add(UnicodeDetector.getInstance());
		java.nio.charset.Charset charset = null;
		try {
			charset = detector.detectCodepage(file.toURI().toURL());
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		if (charset != null) {
			String name = charset.name();
			if (name.startsWith("UTF")) {
				return "UTF-8";
			} else {
				return "GBK";
			}
		}
		return null;
	}

通过此方法可以比较有效的解决解压不同平台压缩的压缩包产生的乱码问题。

结语

文章到这里就结束了,大家可以收藏一下,说不定哪天能用上,或者你有什么更好的方法也欢迎告知我哦,毕竟这个方案并不是完全准确的。今天上班摸鱼更新了一版代码生成器,前后端分离响应式主题现在也支持权限管理模块生成了,同时顺手修复了一些明显的bug,今年已经接近尾声了,大家是不是都在等着年终奖呢,不知道今年发几个月。。。人艰不拆,努力奋斗吧!

关注公众号 螺旋编程极客 发送 zip4j 可获取相关工具包,感兴趣的朋友也可以下载代码生成器使用,期待您的关注!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java解压压缩文件内容时,如果遇到汉字乱码问题,可以使用正确的字符编码来解决。 在解压文件时,可以使用`ZipFile`类和`ZipEntry`类来遍历压缩包中的每个文件,并通过`InputStream`读取文件内容。在读取内容之前,我们可以使用`ZipEntry`的`getEncoding`方法获取文件名的编码格式。如果编码格式不为null,则表示文件使用了特定的编码格式,我们可以使用该编码格式来读取文件内容。 如果文件名的编码格式为null,那么默认使用UTF-8编码来读取文件内容。 例如,以下是使用Java解压文件内容并解决汉字乱码问题的示例代码: ```java import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class UnzipExample { public static void main(String[] args) { try { String zipFilePath = "path/to/your/zipFile.zip"; ZipFile zipFile = new ZipFile(zipFilePath); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); String fileName; if (entry.getEncoding() != null) { fileName = new String(entry.getName().getBytes(StandardCharsets.ISO_8859_1), entry.getEncoding()); } else { fileName = entry.getName(); } System.out.println(fileName); InputStream inputStream = zipFile.getInputStream(entry); // 读取文件内容... inputStream.close(); } zipFile.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 通过在代码中正确地处理文件名的编码格式,我们可以避免解压压缩文件内容时出现汉字乱码问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值