說明
最近開發有將文件打包成zip文件的需求,以供瀏覽器直接點擊下載。這裏可以使用JDK提供的相關方法,也可以使用第三方commons-compress
提供的相關方法,這裏需要注意的是以下幾點:
- 需要滿足可以壓縮文件也可以是文件夾的需求。
- 壓縮的時候能滿足多級目錄的需求。
- 空文件夾如需保存需特殊指明,否則空文件夾並不會進行壓縮。
- 對於任何一個錯誤的文件路徑,其默認類型爲文件夾類型。
JDK方法解壓縮
在解壓縮文件中,使用到的JDK相關類如下所示:
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
可以使用java.util.zip
包中的Deflater
類常量可以指定壓縮級別,這些常數是如下圖所示:
ZipEntry
對象表示Zip
文件格式的歸檔文件中的條目,ZipInputStream
與ZipOutputStream
是讀取zip文件的輸入、輸出流。下面將演示如何解壓縮zip
文件。
- 壓縮文件
/**
* 壓縮文件
* @param zos 輸出流1
* @param file 壓縮的文件對象
*/
public static void compressZipFile(ZipOutputStream zos, File file) {
File[] files = file.listFiles();
try {
if (file.isFile()) {
writeZipEntry(zos, file);
} else {
// 空文件夾
if (files.length == 0) {
ZipEntry zipEntry = new ZipEntry(file.getPath() + File.separator);
zos.putNextEntry(zipEntry);
zos.closeEntry();
}
// 遞歸調用
for (File f : files) {
compressZipFile(zos, f);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 寫zip entry對象
* @param zos
* @param f
*/
private static void writeZipEntry(ZipOutputStream zos, File f) {
BufferedInputStream bis = null;
try {
ZipEntry zipEntry = new ZipEntry(f.getPath());
zos.putNextEntry(zipEntry);
bis = new BufferedInputStream(new FileInputStream(f));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
zos.write(bytes, 0, len);
}
zos.closeEntry();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 解壓文件
/**
* 解壓文件夾
* @param zis 輸入流
* @param path 解壓到path路徑下
*/
public static void deCompressZipFile(ZipInputStream zis, String path) {
ZipEntry zipEntry = null;
try {
while ((zipEntry = zis.getNextEntry()) != null) {
File file = new File(path + File.separator + zipEntry.getName());
// 如果目錄不存在就創建
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
if (!zipEntry.isDirectory()) {
// 讀取Entry對象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] bytes = new byte[1024];
int len;
while ((len = zis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
} else {
file.mkdirs();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
測試執行
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入壓縮的文件目錄");
String line = scanner.nextLine().trim();
File file = new File(line);
if (!file.exists()) {
System.out.println("輸入的路徑不合法");
return;
}
File zipFile = new File("test.zip");
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
zos.setLevel(Deflater.BEST_COMPRESSION);
// 壓縮文件
compressZipFile(zos, file);
zos.close();
File f = new File("test.zip");
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
// 解壓zip
deCompressZipFile(zis, f.getAbsolutePath().replaceAll(File.separator + f.getName(), ""));
zis.close();
}
commons-compress解壓縮
首先引入相關pom依賴如下所示:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
commons-compress是Apache開源組織提供的用於壓縮解壓的工具包,其可以支持以下文件格式的文件解壓縮,如下圖所示:
下面演示如何解壓縮。
- 壓縮文件
/**
*
* @param srcPath 原文件路徑
* @param destFile 壓縮文件路徑
*/
public static void zipFile(String srcPath, String destFile) {
File outFile = new File(destFile);
FileOutputStream fos = null;
BufferedOutputStream bufferedOutputStream = null;
ArchiveOutputStream out = null;
try {
if (!outFile.exists()) {
outFile.createNewFile();
}
fos = new FileOutputStream(outFile);
bufferedOutputStream = new BufferedOutputStream(fos);
out = new ArchiveStreamFactory().createArchiveOutputStream(
ArchiveStreamFactory.ZIP, bufferedOutputStream);
if (srcPath.charAt(srcPath.length() - 1) != '/') {
srcPath += '/';
}
File f = new File(srcPath);
// 如果是文件夾
if(f.isDirectory()) {
Iterator<File> files = FileUtils.iterateFiles(f,
null, true);
System.out.println(f.getAbsolutePath());
while (files.hasNext()) {
File file = files.next();
writeEntry(srcPath, out, file);
}
} else {
writeEntry(srcPath, out, f);
}
out.finish();
out.close();
bufferedOutputStream.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ArchiveException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void writeEntry(String srcPath, ArchiveOutputStream out, File file) throws IOException {
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,
file.getPath().replace(srcPath.replace("/", "\\"), ""));
out.putArchiveEntry(zipArchiveEntry);
IOUtils.copy(new FileInputStream(file), out);
out.closeArchiveEntry();
}
- 解壓文件
public static void deCompressZip(String zipPath) throws Exception
{
InputStream stream = new FileInputStream(zipPath);
ZipArchiveInputStream inputStream = new ZipArchiveInputStream(stream);
ZipArchiveEntry entry = null;
while ((entry = inputStream.getNextZipEntry()) != null)
{
System.out.println(entry.getName());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//讀取內容
IOUtils.copy(inputStream, outputStream);
System.out.println(outputStream.toString());
}
inputStream.close();
stream.close();
}