压缩/解压缩 在java项目中的使用。
包含了两个操作:压缩、解压缩
包含了本地文件、web文件的操作:
- 压缩本地文件保存到本地
- 压缩网络文件保存到本地
- 本地压缩包文件解压到本地
- 压缩网络文件为文件流供web下载
- 读取zip/jar等压缩包内的文件并打印其文本内容
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* @author mengwei18
*/
@Slf4j
public class ZipUtils {
private static final String KEY = "file.encoding";
private static final String ENCODING = "GBK";
private static final int BUFFER_SIZE = 2 * 1024;
/**
* 压缩成ZIP:压缩本地文件保存到本地专用
*
* @param filePaths 需要压缩的文件(本地文件)
* @param zipFilePath 压缩成的文件名称(建议.zip结尾)
* @throws IOException 压缩失败会抛出运行时异常
*/
public static void zip(List<String> filePaths, String zipFilePath) throws IOException {
OutputStream outputStream = Files.newOutputStream(Paths.get(zipFilePath));
long start = System.currentTimeMillis();
ZipOutputStream zos = new ZipOutputStream(outputStream);
try {
for (String filePath : filePaths) {
// 如果图片路径为空则跳过
if (StringUtils.isBlank(filePath)) {
continue;
}
compress(zos, Files.newInputStream(Paths.get(filePath)), filePath.substring(filePath.lastIndexOf("/") + 2));
}
zos.closeEntry();
long end = System.currentTimeMillis();
log.info("压缩完成,耗时:{} ms", (end - start));
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 压缩成ZIP:压缩网络文件保存到本地专用
*
* @param fileUrls 需要压缩的文件(网络文件)
* @param zipFilePath 压缩成的文件名称(建议.zip结尾)
* @throws IOException 压缩失败会抛出运行时异常
*/
public static void zipWebFiles(List<String> fileUrls, String zipFilePath) throws IOException {
OutputStream outputStream = Files.newOutputStream(Paths.get(zipFilePath));
long start = System.currentTimeMillis();
ZipOutputStream zos = new ZipOutputStream(outputStream);
try {
for (String fileUrl : fileUrls) {
// 如果图片路径非http开头则跳过
if (StringUtils.isBlank(fileUrl) || !fileUrl.startsWith("http")) {
continue;
}
compress(zos, getInputStreamFromWebFile(fileUrl), fileUrl.substring(fileUrl.lastIndexOf("/") + 2));
}
zos.closeEntry();
long end = System.currentTimeMillis();
log.info("压缩完成,耗时:{} ms", (end - start));
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 本地压缩包文件解压到本地
*
* @param zipFilePath 本地压缩包文件名称
* @param destDir 解压后本地存储的目标目录
*/
public static void unzip(String zipFilePath, String destDir) {
try {
File destDirFile = new File(destDir);
if (!destDirFile.exists()) {
destDirFile.mkdirs();
}
ZipInputStream zipIn = new ZipInputStream(Files.newInputStream(Paths.get(zipFilePath)));
ZipEntry entry;
while ((entry = zipIn.getNextEntry()) != null) {
String filePath = destDir + File.separator + entry.getName();
if (!entry.isDirectory()) {
extractFile(zipFilePath, zipIn, filePath);
} else {
File dir = new File(filePath);
dir.mkdirs();
}
zipIn.closeEntry();
}
zipIn.close();
} catch (IOException e) {
log.error("解压异常, zipFilePath={}", zipFilePath);
}
}
private static void extractFile(String zipFilePath, ZipInputStream zipIn, String filePath) {
try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(Paths.get(filePath)))) {
byte[] bytesIn = new byte[4096];
int read;
while ((read = zipIn.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
} catch (Exception ignore) {
log.error("解压中发现不存在的文件, zipFilePath={}, filePath={}", zipFilePath, filePath);
}
}
/**
* 压缩成ZIP:web请求专用,会转化为文件流供web下载
*
* @param fileUrls 需要压缩的文件(网络文件)
* @param response 文件流输出的response
* @throws IOException 压缩失败会抛出运行时异常
*/
public static void toZipResponse(List<String> fileUrls, HttpServletResponse response) throws IOException {
long start = System.currentTimeMillis();
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
try {
for (String fileUrl : fileUrls) {
// 如果图片路径非http开头则跳过
if (StringUtils.isBlank(fileUrl) || !fileUrl.startsWith("http")) {
continue;
}
compress(zos, getInputStreamFromWebFile(fileUrl), fileUrl.substring(fileUrl.lastIndexOf("/") + 2));
}
zos.closeEntry();
long end = System.currentTimeMillis();
log.info("压缩完成,耗时:{} ms", (end - start));
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static InputStream getInputStreamFromWebFile(String url) {
if (StringUtils.isBlank(url)) {
return null;
}
URLConnection con;
HttpURLConnection httpCon;
try {
System.setProperty(KEY, ENCODING);
con = new URL(url).openConnection();
con.setConnectTimeout(3000);
con.setUseCaches(false);
con.setDefaultUseCaches(false);
if (con instanceof HttpURLConnection) {
httpCon = (HttpURLConnection) con;
httpCon.setInstanceFollowRedirects(true);
if (httpCon.getResponseCode() >= 300) {
System.out.println("URL:" + url + ",HTTP Request is not success, Response code is " + httpCon.getResponseCode());
} else {
return httpCon.getInputStream();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 递归压缩方法
*
* @param zos zip输出流
*/
private static void compress(ZipOutputStream zos, InputStream fileInputStream, String fileName) throws Exception {
if (fileInputStream == null || StringUtils.isBlank(fileName)) {
return;
}
byte[] buf = new byte[BUFFER_SIZE];
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(fileName));
// copy文件到zip输出流中
int len;
while ((len = fileInputStream.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
fileInputStream.close();
}
/**
* 读取zip/jar等压缩包内的文件并打印其文本内容
*
* @param zipFilePath 本地压缩包文件名称
*/
public static void readZipFileContent(String zipFilePath) throws Exception {
ZipFile zipFile = new ZipFile(zipFilePath);
InputStream inputStream = new BufferedInputStream(Files.newInputStream(Paths.get(zipFilePath)));
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
java.util.zip.ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (!zipEntry.isDirectory()) {
PrintUtil.print("file - " + zipEntry.getName() + " : " + zipEntry.getSize() + " bytes");
long size = zipEntry.getSize();
if (size > 0) {
BufferedReader br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipEntry)));
String line;
while ((line = br.readLine()) != null) {
PrintUtil.print(line);
}
br.close();
}
PrintUtil.print();
}
}
zipInputStream.closeEntry();
zipInputStream.close();
inputStream.close();
zipFile.close();
}
}