2021SC@SDUSC
目录
zip文件解压都封装在ZipUtils类中,先来分析zip文件的读取方法readZipFile()
读取zip文件
-filepath:文件路径
-filekey:文件标识
方法开头先创建如下变量:
-map变量appender:方便以后存取数据
-列表imgurl:存放解压出来的图片地址
-字符串archiveFileName:获取压缩包的文件名
之后进行一个try-catch语句,创建Enumeration<ZipArchiveEntry>变量entries存放压缩包zip的文件实体,调用自定义的sortZipEntries()方法对实体进行排序,并将排序完成后的entries存入队列entriesToBeExtracted。
之后进入while循环,声明ZipArchiveEntry变量entry,赋值为zip文件中的文件实体,定义string-key为实体的文件名。文件名分为originName部分和chhildName部分,childName只有在文件不是目录directory的前提下才可赋值。调用getLast2FileNmae获取parentName。如果childName中的url-typr是图片,则将图片文件添加到图片列表中。
最后开启新的线程处理文件解压。
public String readZipFile(String filePath,String fileKey) {
String archiveSeparator = "/";
Map<String, FileNode> appender = Maps.newHashMap();
List<String> imgUrls = Lists.newArrayList();
String baseUrl = BaseUrlFilter.getBaseUrl();
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
try {
ZipFile zipFile = new ZipFile(filePath, fileUtils.getFileEncodeUTFGBK(filePath));
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
// 排序
entries = sortZipEntries(entries);
List<Map<String, ZipArchiveEntry>> entriesToBeExtracted = Lists.newArrayList();
while (entries.hasMoreElements()){
ZipArchiveEntry entry = entries.nextElement();
String fullName = entry.getName();
int level = fullName.split(archiveSeparator).length;
// 展示名
String originName = getLastFileName(fullName, archiveSeparator);
String childName = level + "_" + originName;
boolean directory = entry.isDirectory();
if (!directory) {
childName = archiveFileName + "_" + originName;
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
}
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
parentName = (level-1) + "_" + parentName;
FileType type=fileUtils.typeFromUrl(childName);
if (type.equals(FileType.picture)){//添加图片文件到图片列表
imgUrls.add(baseUrl+childName);
}
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey);
addNodes(appender, parentName, node);
appender.put(childName, node);
}
// 开启新的线程处理文件解压
executors.submit(new ZipExtractorWorker(entriesToBeExtracted, zipFile, filePath));
fileUtils.putImgCache(fileKey,imgUrls);
return new ObjectMapper().writeValueAsString(appender.get(""));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
对zip实体进行排序
调用list的sort方法,使用java.util.Comparator 创建一个比较器调用comparingInt方法,sort 对象接收一个 Comparator 函数式接口,可以传入一个lambda表达式。放在这里指按照名字长度排序。
private Enumeration<ZipArchiveEntry> sortZipEntries(Enumeration<ZipArchiveEntry> entries) {
List<ZipArchiveEntry> sortedEntries = new LinkedList<>();
while (entries.hasMoreElements()) {
sortedEntries.add(entries.nextElement());
}
sortedEntries.sort(Comparator.comparingInt(o -> o.getName().length()));
return Collections.enumeration(sortedEntries);
}
添加节点
往传入参数appender中包含parentname的对象添加childname节点
private void addNodes(Map<String, FileNode> appender, String parentName, FileNode node) {
if (appender.containsKey(parentName)) {
appender.get(parentName).getChildList().add(node);
appender.get(parentName).getChildList().sort(sortComparator);
} else {
// 根节点
FileNode nodeRoot = new FileNode(parentName, parentName, "", new ArrayList<>(), true);
nodeRoot.getChildList().add(node);
appender.put("", nodeRoot);
appender.put(parentName, nodeRoot);
}
}
文件名倒数第二部分获取
private static String getLast2FileName(String fullName, String seperator, String rootName) {
if (fullName.endsWith(seperator)) {
fullName = fullName.substring(0, fullName.length() - 1);
}
// 1.获取剩余部分
int endIndex = fullName.lastIndexOf(seperator);
String leftPath = fullName.substring(0, endIndex == -1 ? 0 : endIndex);
if (leftPath.length() > 1) {
// 2.获取倒数第二个
return getLastFileName(leftPath, seperator);
} else {
return rootName;
}
}
FileNode属性
分为目录(根节点)和普通节点,directory是用在zip中是文件时要寻址时用的。
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory) {
this.originName = originName;
this.fileName = fileName;
this.parentFileName = parentFileName;
this.childList = childList;
this.directory = directory;
}
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory, String fileKey) {
this.originName = originName;
this.fileName = fileName;
this.parentFileName = parentFileName;
this.childList = childList;
this.directory = directory;
this.fileKey = fileKey;
}