在线压缩和解压缩
最近在做服务端的文件压缩与解压缩操作,下面是一些可能会用到的工具方法。
服务端操作zip压缩包可以使用java提供的zip类相关方法。
涉及到文件流输出,文件流写入。
工具类
package pers.os467.support.utils.zip;
import pers.os467.support.utils.IOUtils;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* ZIP工具类
* author: os467
*/
public class ZipFileUtils {
/**
* 获取zip条目所属目录条目名称
* @param name
* @return
*/
public static String getEntryDirName(String name){
if (name.endsWith("/")){
//查询其上一级条目
String last = name.substring(0, name.lastIndexOf("/"));
if (!last.contains("/")){
//无上一级目录
return null;
}else {
//返回目录名
return last.substring(0,last.lastIndexOf("/")+1);
}
}else {
if (name.contains("/")){
return name.substring(0, name.lastIndexOf("/")+1);
}else {
//无上一级目录
return null;
}
}
}
/**
* 解压缩,保存文件夹结构
* @param zipFile
* @param outPutPath
*/
public static void unzip(ZipFile zipFile,String outPutPath){
File file = new File(outPutPath);
if (file.exists()){
if (!file.isDirectory()){
throw new RuntimeException("output path not a directory");
}
}else {
file.mkdirs();
}
Enumeration<? extends ZipEntry> entries = zipFile.entries();
//将zip文件集合读出
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.isDirectory()){
continue;
}
//非目录
String dirs = zipEntry.getName().substring(0, zipEntry.getName().lastIndexOf("/") + 1);
File df = new File(outPutPath + File.separator + dirs);
df.mkdirs();
File outPut = new File(outPutPath + File.separator + zipEntry.getName());
writeEntryToFile(zipFile, zipEntry, outPut);
}
}
/**
* 将zip内部条目解压缩到指定文件
* @param zipFile
* @param zipEntry
* @param outPut
*/
public static void writeEntryToFile(ZipFile zipFile, ZipEntry zipEntry, File outPut) {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outPut);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
InputStream inputStream = zipFile.getInputStream(zipEntry);
IOUtils.copy(inputStream,outputStream);
} catch (IOException ioException) {
ioException.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
/**
* 压缩文件
* @param files 条目 : 输出文件
* @param zipFileOutPutPath 文件输出路径
*/
public static void zipFile(Map<String, File> files,String zipFileOutPutPath){
//压缩文件
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFileOutPutPath);
zipFilesToOutPutStream(files,fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* 将输出流包装为zip输出流并按照文件结构映射打包文件
* @param files key为zip中的路径,分隔符必须使用"/" value为文件对象,若为null如果是目录则创建空目录
* 例如
* 新建文件夹1/ -> null
* 新建文件夹1/新建文件夹2 -> null
* 新建文件夹/1.txt -> new File(".../1.txt")
* 新建文件夹1/新建文件夹2/2.txt -> new File(".../2.txt")
* @param out 输出流
* @throws IOException
*/
public static void zipFilesToOutPutStream(Map<String, File> files, OutputStream out) throws IOException {
if (files.size() == 0){
//创建空zip
try (ZipOutputStream zos = new ZipOutputStream(out)){//do nothing...
}
return;
}
// 创建一个ZipOutputStream对象,它将用于写入压缩数据
try (ZipOutputStream zos = new ZipOutputStream(out)) {
// 遍历文件映射
for (Map.Entry<String, File> entry : files.entrySet()) {
// 获取文件的ZIP路径和对应的文件对象
String name = entry.getKey();
File file = entry.getValue();
//如果是目录则创建空目录 例如name = dir1/dir2/
if (file == null) {
zos.putNextEntry(new ZipEntry(name));
zos.closeEntry();
continue;
}
// 如果文件对象不是一个文件,抛出异常
if (!file.isFile()) {
throw new IllegalArgumentException("Only files are supported");
}
// 创建一个新的ZIP条目并将其添加到ZIP输出流中 例如: name = dir1/dir2/fileName
// 这里的name就是文件在压缩包中的路径,包括多级目录
zos.putNextEntry(new ZipEntry(name));
// 创建一个输入流来读取文件的内容
try (InputStream in = new FileInputStream(file)) {
// 创建一个缓冲区
byte[] buffer = new byte[1024];
int len;
// 读取文件内容并写入ZIP输出流
while ((len = in.read(buffer)) != -1) {
zos.write(buffer, 0, len);
}
}
// 关闭当前ZIP条目,使其写入ZIP文件
zos.closeEntry();
}
}
}
/**
* 获取zip条目文件名
* @param name
* @return
*/
public static String getEntryFileName(String name) {
if (name.endsWith("/")){
//文件夹
String s = name.substring(0, name.length() - 1);
return s.substring(s.lastIndexOf("/") + 1);
}else {
//非文件夹
if (name.contains("/")){
return name.substring(name.lastIndexOf("/") + 1);
}else {
return name;
}
}
}
/**
* 集合去重计算文件总数量
* @param zipFile
* @return
*/
public static Integer countFileNum(ZipFile zipFile) {
Set<String> set = new HashSet<>();
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
String name = zipEntry.getName();
if (name.contains("/")){
String[] path = name.split("/");
String build = "";
for (int i = 0; i < path.length - 1; i++) {
build += path[i] + "/";
set.add(build);
}
}
set.add(name);
}
return set.size();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com