踩坑日志一
最近做了个新的功能,是将zip压缩文件解压成流之后再进行保存上传,在实现过程中发现了严重的问题,不同操作系统的压缩文件解压之后文件名会出现乱码,当时就用了临时的方案来解决了。在开始之前,我们先了解一下不同操作系统压缩文件使用的字符集。
1、Windows操作系统压缩的文件默认使用gbk的字符集编码。
2、Mac和Linux操作系统压缩的文件默认使用utf8的字符集编码。
所以你可以想到的第一个想法是,我可以通过拿到的文件,然后通过获取文件头信息拿到它的操作系统,就可以根据这个文件是哪个操作系统用对应的编码去解压;但是你有没有想一件事,如果是一个客户在Mac压缩文件把他发给另一个windows的人进行操作呢,那针对这种我目前是没想到好的解决,哈哈。
接下来就是这次用的方案了(目前觉得不是最好的,临时的),这次用的解压类是ZipInputStream,代码如下:
下面展示一些 测试用例。
@Test
public void unzip() throws IOException{
String fileName = "3.zip";
String filePath = "D:\\3.zip";
MultipartFile multipartFile = new MockMultipartFile(fileName, new FileInputStream(filePath));
try {
ZipInputStream zipInputStream = new ZipInputStream(multipartFile.getInputStream(), Charset.forName("UTF-8"));
this.updateInputStream(zipInputStream);
System.out.println("======解压成功=======");
} catch (IllegalArgumentException ie) {
System.out.println("压缩包处理异常,异常信息"+ie.getMessage());
ZipInputStream zipInputStream = new ZipInputStream(multipartFile.getInputStream(), Charset.forName("GBK"));
this.updateInputStream(zipInputStream);
} catch (IOException e) {
System.out.println("压缩包处理异常,异常信息"+e.getMessage());
}
}
private void updateInputStream(ZipInputStream zipInputStream) throws IOException {
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
System.out.println(fileName);
if (!zipEntry.getName().contains("MACOSX") && zipEntry.getName().contains(".pdf")) {//苹果压缩的文件夹不处理,只处理pdf的文件
if (zipEntry.isDirectory()) {
// 找到目标文件夹
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (!zipEntry.isDirectory()) {
// 输出或处理找到的文件并处理文件名
String path = zipEntry.getName();
int lastIndex = path.lastIndexOf("/");
String result = path.substring(lastIndex + 1);
}
break;
}
} else {
String path = zipEntry.getName();
int lastIndex = path.lastIndexOf("/");
String result = path.substring(lastIndex + 1);
}
}
zipEntry = zipInputStream.getNextEntry();
}
}
接下来代码分析:
一开始是用windows压缩的文件进行测试,我们一开始用utf8字符集编码方式解压,此时解压过程中执行了ZipEntry zipEntry = zipInputStream.getNextEntry()这一段代码,抛出MALFORMED异常,这个异常就是字符集编码的问题,因为我们用了windows的压缩文件(字符集gdk),解压方式是用utf8字符集,因此直接捕获这个异常后面重新用gbk方式去处理压缩文件。
错误方式:
那假如我都用gbk去处理文件会发生什么呢
此时windows压缩文件是正常的。
接下来使用Mac压缩的文件去处理:
此时我们就可以看到乱码了,后面就不截图utf8的解压方式了。