1 场景:
今天需要打包一些文件下载,用压缩包的方式实现。但是完成开发工作后台发现一堆乱码。
2 思路及解决问题:
2.1 解决docker乱码
发版测试环境使用的docker,于是检查了docker的语言支持环境。做法,首先我是在linux上面直接使用命令创建的文件夹:mkdir 测试,发现乱码。
然后查看了语言环境的支持,locale,
发现zh_CN.UTF-8的语言包不存在,因为是docker环境,所以没有再去安装语言包,直接用了已经有的语言支持。locale -a | grep utf8
直接找到dockerfile文件,修改其中的语言环境
修改完成后,重新部署了下服务,测试下mkdir 测试.
docker的乱码问题解决了,但是,压缩包下载依然有乱码。
2.2 解决zip打包压缩后文件内路径及文件乱码问题
docker可以使用命令创建中文文件及文件夹了,但是使用代码创建的依旧为乱码,在网上个中搜索以后,不得已做了以下测试。
String file1 = dirFirst;
String str = new String("测试1".getBytes(),"UTF-8");
String str1 = new String("测试2".getBytes(),"UTF8");
String str2 = new String("测试3".getBytes(),"gbk");
String str3 = new String("测试4".getBytes(),"gb2312");
String str4 = new String("测试5".getBytes("ISO-8859-1"),"utf-8");
String str5 = new String("测试6".getBytes("ISO-8859-1"),"GBK");
String str6 = new String("测试7".getBytes("ISO-8859-1"),"gb2312");
String file = file1 + str;
File dir = new File(file);
dir.mkdirs();
file = file1 + str1;
dir = new File(file);
dir.mkdirs();
file = file1 + str2;
dir = new File(file);
dir.mkdirs();
file = file1 + str3;
dir = new File(file);
dir.mkdirs();
file = file1 + str4;
dir = new File(file);
dir.mkdirs();
file = file1 + str5;
dir = new File(file);
dir.mkdirs();
file = file1 + str6;
dir = new File(file);
dir.mkdirs();
发现最后如果要使用代码来创建文件夹及文件,需要utf8转码。至此服务器上已经可以用代码创建中文文件了。但是最终问题还未解决。下载后的文件依旧乱码。继续查询资料。网上很多资料说把ZipEntry需要依赖于ant的包,但是问题并没有得到解决,依旧乱码。最终:
ZipEntry zipEntry = new ZipEntry(name);
zipEntry.setUnixMode(644); //解决文件名称乱码用644 解决文件夹名称乱码用755
zos.putNextEntry(zipEntry);
整个zip包的关键代码如下,引用的依赖为ant:
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.6.5</version>
</dependency>
private void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException{
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure) throws Exception{
byte[] buf = new byte[2 * 1024];
if(sourceFile.isFile()){
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
ZipEntry zipEntry = new ZipEntry(name);
zipEntry.setUnixMode(644);
zos.putNextEntry(zipEntry);
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if(listFiles == null || listFiles.length == 0){
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if(KeepDirStructure){
// 空文件夹的处理
ZipEntry zipEntry = new ZipEntry(name + "/");
zipEntry.setUnixMode(755);
zos.putNextEntry(zipEntry);
// 没有文件,不需要文件的copy
zos.closeEntry();
}
}else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
} else {
compress(file, zos, file.getName(),KeepDirStructure);
}
}
}
}
}
至此,整个zip导出中文乱码处理干净了。