java压缩与解压
一 概述
1.目录进入点
目录进入点是文件在压缩文件中的映射,代表压缩文件。压缩文件时,创建目录进入点,将文件写入该目录进入点。解压时,获取目录进入点,将该目录进入点的内容写入硬盘指定文件。
如果目录进入点是一个文件夹,在命名时必须以路径分隔符结尾,在Window操作系统中名称分隔符为“/”。
2.文件的自动创建
无论是调用createNewFile()创建文件,还是在创建输出流时由输出流负责创建文件,都必须保证父路径已经存在,否则文件无法创建。
3.目录的创建
- mkdirs():创建多级目录。
- mkdir():创建一级目录,如果父路径不存在,创建失败。
二 压缩
1.创建目录进入点
首先为文件或者文件夹创建目录进入点,目录进入点的名称为当前文件相对于压缩文件的路径,文件夹的目录进入点名称必须以名称分隔符结尾,以区别于文件。
ZipEntry entry = new ZipEntry(压缩文件夹名称 + File.separator+文件或文件夹路径);
2.写入目录进入点
使用ZipOutputStream输出流将文件写入对应目录进入点中,写入完成,关闭目录进入点。
3.Demo
package com.javase.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class ZipUtils { /** * 压缩一个文件夹 * * @throws IOException */ public void zipDirectory(String path) throws IOException { File file = new File(path); String parent = file.getParent(); File zipFile = new File(parent, file.getName() + ".zip"); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)); zip(zos, file, file.getName()); zos.flush(); zos.close(); } /** * * @param zos * 压缩输出流 * @param file * 当前需要压缩的文件 * @param path * 当前文件相对于压缩文件夹的路径 * @throws IOException */ private void zip(ZipOutputStream zos, File file, String path) throws IOException { // 首先判断是文件,还是文件夹,文件直接写入目录进入点,文件夹则遍历 if (file.isDirectory()) { ZipEntry entry = new ZipEntry(path + File.separator);// 文件夹的目录进入点必须以名称分隔符结尾 zos.putNextEntry(entry); File[] files = file.listFiles(); for (File x : files) { zip(zos, x, path + File.separator + x.getName()); } } else { FileInputStream fis = new FileInputStream(file);// 目录进入点的名字是文件在压缩文件中的路径 ZipEntry entry = new ZipEntry(path); zos.putNextEntry(entry);// 建立一个目录进入点 int len = 0; byte[] buf = new byte[1024]; while ((len = fis.read(buf)) != -1) { zos.write(buf, 0, len); } zos.flush(); fis.close(); zos.closeEntry();// 关闭当前目录进入点,将输入流移动下一个目录进入点 } } }
三 解压文件
1.基本思路
解压文件时,先获取压缩文件中的目录进入点,根据该目录进入点创建文件对象,将目录进入点的内容写入硬盘文件中。
2.Demo
package com.javase.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class ZipUtils {private String basePath; /** * 解压文件 * * @param unzip * @throws IOException */ public void unzip(String unzip) throws IOException { File file = new File(unzip); basePath = file.getParent(); FileInputStream fis = new FileInputStream(file); ZipInputStream zis = new ZipInputStream(fis); unzip(zis); } private void unzip(ZipInputStream zis) throws IOException { ZipEntry entry = zis.getNextEntry(); if (entry != null) { File file = new File(basePath + File.separator + entry.getName()); if (file.isDirectory()) { // 可能存在空文件夹 if (!file.exists()) file.mkdirs(); unzip(zis); } else { File parentFile = file.getParentFile(); if (parentFile != null && !parentFile.exists()) parentFile.mkdirs(); FileOutputStream fos = new FileOutputStream(file);// 输出流创建文件时必须保证父路径存在 int len = 0; byte[] buf = new byte[1024]; while ((len = zis.read(buf)) != -1) { fos.write(buf, 0, len); } fos.flush(); fos.close(); zis.closeEntry(); unzip(zis); } } } }
不能仅仅停滞在实现上,应该去追求代价更小、性能更优的实现