记录一个java解压zip包的代码,没啥难度,就主要下面两个注意点:
- zip大多数是windows系统下,所以使用GBK
Charset.forName("GBK")
格式,不然会报错 - 空文件夹不能用
file.isDirectory()
处理,网上大多数文档都是这么处理会有问题,具体详见代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@RestController
@RequestMapping("/test")
public class ZipUploadController {
@PostMapping(value = "/uploadZip", headers = "content-type=multipart/*")
public String uploadZip(@RequestParam("zipFile") MultipartFile zipFile) throws Exception {
//解压后存放的目标文件夹
String path = "C:/Users/Administrator/Desktop/zipTest/";
File newFile = new File(path + zipFile.getOriginalFilename());
zipFile.transferTo(newFile);
zipUncompress(newFile, path);
return "success";
}
/**
* zip文件解压
*/
public static void zipUncompress(File srcFile, String destDirPath) throws Exception {
// 判断源文件是否存在
if (!srcFile.exists()) {
throw new Exception(srcFile.getPath() + "所指文件不存在");
}
ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK"));//创建压缩文件对象
//开始解压
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
// 如果是文件夹,就创建个文件夹
if (entry.getName().endsWith("/") || entry.getName().endsWith("\\")) {
File dir = new File(destDirPath +
entry.getName().substring(0, entry.getName().length() - 1));//空文件的结尾带/
if (!dir.exists()) {
dir.mkdirs();
}
} else {
InputStream is = null;
FileOutputStream fos = null;
try {
// 如果是文件,就先创建一个文件,然后用io流把内容copy过去
File targetFile = new File(destDirPath + "/" + entry.getName());
// 保证这个文件的父文件夹必须要存在
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
// 将压缩文件内容写入到这个文件中
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关流顺序,先打开的后关闭
if(fos != null){
fos.close();
}
if(is != null){
is.close();
}
}
}
}
}
}
上面是上传并解压zip包,解压后拿到解压的文件File
,这里提供一个自己临时写的工具类,可以把解压后的文件解析到文件树对象中,方便获取每一级的文件和下级文件
import com.google.common.collect.Lists;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import java.io.File;
import java.util.List;
/**
* 文件树
*
* @author zx
*/
@Data
public class FileTreeNode {
/**
* 文件名称
*/
private String name;
/**
* 文件内容
*/
private File file;
/**
* 当前文件所属层级
*/
private int level;
/**
* 类型 1:文件夹 2:文件
*/
private int type;
/**
* 下级文件
*/
private List<FileTreeNode> nextNodes;
/**
* 是否有下级
*/
public boolean hasNext() {
return nextNodes != null && nextNodes.size() > 0;
}
/**
* 是不是文件夹
*/
public boolean isDirectory() {
return type == 1;
}
/**
* 是不是文件
*/
public boolean isFile() {
return type == 2;
}
/**
* 加载这个文件下的文件树 包括文件夹和文件
*
* @param file 要加载的文件
* @param readMaxLevel 最大读多少层 该值小于1则表示有多少层读取多少层
* @return
*/
public static FileTreeNode readZipFile(File file, int readMaxLevel) {
return readZipFile(file, 0, readMaxLevel);
}
private static FileTreeNode readZipFile(File file, int fileLevel, int readMaxLevel) {
if (readMaxLevel > 0 && fileLevel > readMaxLevel) {
return null;
}
// 取得文件目录中所有文件的File对象数组
File[] files = file.listFiles();
if (files == null || files.length < 1) {
return null;
}
FileTreeNode fileTreeNode = new FileTreeNode();
int i = file.getName().lastIndexOf(".");
if (i >= 0) {
fileTreeNode.setName(file.getName().substring(0, i));
} else {
fileTreeNode.setName(file.getName());
}
fileTreeNode.setFile(file);
fileTreeNode.setLevel(fileLevel);
if (file.isDirectory()) {
//文件夹
fileTreeNode.setType(1);
} else {
//文件
fileTreeNode.setType(2);
}
if (CollectionUtils.isEmpty(fileTreeNode.getNextNodes())) {
fileTreeNode.setNextNodes(Lists.newArrayList());
}
fileLevel++;
// 遍历file数组
for (File nextFile : files) {
FileTreeNode nextTreeNode = new FileTreeNode();
int x = nextFile.getName().lastIndexOf(".");
if (x >= 0) {
nextTreeNode.setName(nextFile.getName().substring(0, x));
} else {
nextTreeNode.setName(nextFile.getName());
}
nextTreeNode.setFile(nextFile);
nextTreeNode.setLevel(fileLevel);
if (nextFile.isDirectory()) {
nextTreeNode.setType(1);
// 递归子目录
FileTreeNode fileTreeNode1 = readZipFile(nextFile, fileLevel, readMaxLevel);
if (fileTreeNode1 != null) {
fileTreeNode.getNextNodes().add(fileTreeNode1);
}
} else {
nextTreeNode.setType(2);
fileTreeNode.getNextNodes().add(nextTreeNode);
}
}
return fileTreeNode;
}
public static void main(String[] args) {
FileTreeNode fileTreeNode = FileTreeNode.readZipFile(new File("C:\\Users\\Administrator\\Desktop\\xxxxxx"), 0);
System.out.println(JSONObject.toJSONString(fileTreeNode));
}
}
解析文件夹并生成文件树对象的这个代码是自己随便写的,存在问题欢迎指正,目前我使用中未发现问题
当然你也可以直接使用工具类:org.apache.commons.io的FileUtils.listFilesAndDirs()