上一篇 Java 类别的文章中介绍了一下 Java 中普通文件的相关操作,包括:文件读取和写入、文件复制、文件移动等操作。
这一篇来看一下 Java API 对 ZIP 压缩格式的文件的相关操作。
一、 压缩文件/文件夹
先从压缩文件开始吧,先来看一下一个普通的压缩文件的内容:
这是一个简单的 ZIP 格式的压缩文件,打开之后可以看到里面有很多项,包括文件夹和文件,我们在压缩这些文件时往往会先将要压缩的文件选中,然后再将它们压缩成一个压缩文件。在 Java 的 ZIP 压缩文件 API 中,每一个文件/文件夹在压缩时都被看成是一个“入口”对象(ZipEntry 对象),压缩时,有几个文件/文件夹,就需要创建几个“入口”对象(ZipEntry 对象)。下面看一下压缩一个文件/文件夹的基本步骤:
假设现在对一个名为 a 的文件/文件夹进行压缩
1、判断 a 是否为一个文件/文件夹,如果 a 为一个文件,那么创建一个新的同名"入口"对象(ZipEntry 对象),并且运用 API 将文件 a 中的内容写入这个"入口"对象(ZipEntry 对象)中。结束压缩。
2、如果 a 是一个文件夹,那么我们仍需要创建一个新的同名"入口"对象(ZipEntry 对象),之后对 a 文件夹里面的每一个文件/文件夹进行递归压缩(因为我们并不知道 a 的子文件是否全是文件/全是文件夹)。
Ok,明白了压缩过程之后我们来看一下其相关的 API:
ZipOutputStream 类:我们知道,对普通文件操作时,如果需要将文件输出,则需要使用 OutputStream 的子类来进行写数据操作。同样的,对于 ZIP 格式压缩文件,我们需要用 ZipOutputStream 类来对其进行数据写入等操作。
其常用的方法有:
putNextEntry(ZipEntry e) // 在压缩文件中添加一个新的"入口"
close() // 结束数据写入并且关闭压缩文件流
write(byte[] b, int off, int len) // 将数组 b 中的数据写入数据到当前 ZIP 文件流中, off 为从数组 b 中开始读取的数据的偏移量(字节),len 为写入数据的长度(字节)
finish () // 结束数据写入但是不关闭压缩文件流
setComment(String comment) // 设置压缩文件的注释,打开这个压缩文件时能看到
....
基本的 API 就这些了,下面来实践一下,压缩一个文件/文件夹,先上代码:
/**
* compress file or dictionary what named inputName by zip form and save it to the load of outputName as a zip file
* if param inputName is null or the file of it represent is not exists,
* this method will throws new IllegalArgumentException;
* 以 zip 格式压缩路径为 inputName 的文件/文件夹,并且将其压缩后的 zip 文件保存在路径为 outputName 的文件,
* 如果 inputName 所代表的文件/文件夹不存在,将会抛出一个 IllegalArgumentException
* @param inputName the file of you want to compress
* @param outputName the output file path which you want to save the zip file
*/
public static void compressFile(@NotNull String inputName, @NotNull String outputName) throws IOException {
if (inputName == null || outputName == null) {
throw new IllegalArgumentException("input name and output name can't be null");
}
File inputFile = new File(inputName);
if (!inputFile.exists()) {
throw new IllegalArgumentException("The input file does not exists!");
}
// 创建一个新的 ZipOutputStream 对象
ZipOutputStream output = new ZipOutputStream(new FileOutputStream(outputName));
System.out.println("正在压缩中...");
long startTime = System.currentTimeMillis();
// 设置压缩文件注释
output.setComment("This is my zip file");
// 开始压缩文件
zipFile(output, inputFile, "");
long endTime = System.currentTimeMillis();
System.out.println("压缩完成");
System.out.println("压缩用时:" + String.valueOf(((double) endTime-startTime)/1000) + "秒");
// 结束压缩文件
output.close();
}
/**
* compress current file as zip form and save the result file as the sub file of folder that basePath represent
* 将当前文件(currentFile)压缩到 basePath 文件夹下,basePath 为相对压缩文件的相对路径
* @param zOut the outputStream of zip file
* @param currentFile current file that will be compressed
* @param basePath the path of current file will be saved,relative to compress file
*/
private static void zipFile(@NotNull