ZipInputStreamhe和ZipOutputStream这两个类本身不具备读写文件的能力,这两个类都间接继承自Filter Input Stream,因此它们的构造方法允许传入一个真正具备读写功能的字符流对象。如FileInputStream和FileOutputStream的对象,从尾完成文件的读写。
首先创建一个zipInputStream的对象,zip文件中的每一个文件都是一个ZipEntry对象,通过zipInputStream对象调用getNextEntry()方法获取这些文件到输入流中。然后通过输入流和输出流完成文件的读写。
读取Zip包(解压缩)
首先要创建解压缩目录sourceDir,通常是与zip文件在同一个目录下,通过用zip文件的父目录与zip文件的文件名作为数据源,并调用mkdir()方法创建目录。
第二步就是解析并读取zip压缩文件,创建一个ZipInputStream,传入一个FileInputStream作为数据源,然后循环调用getNextEntry(),遍历zip文件每个子文件,每次循环获取子文件的文件名并创建该文件的输出流,调用write()方法,读取文件内容并写入输出流。
public class Test02 {public static void main(String[] args) {// String path = "D:\\1\\文件夹\\easyftp-server-1.7.0.10-cn.zip";String path = "D:\\1\\文件夹\\实验案例.rar";if (path.endsWith("zip")) {unzip(path);} else if (path.endsWith("rar")) {unrar(path);}}// 解压缩zip格式public static void unzip(String path) {// 根据原始路径(字符串),创建源文件(File对象)File sourceFile = new File(path);// 根目录String sourceFilename = sourceFile.getName();File rootDir = new File(sourceFile.getParent() + "\\" + sourceFilename.substring(0, sourceFilename.lastIndexOf(".")));// 判断根目录是否存在if (rootDir.exists()) {// 如果存在,则删除// 使用commons-io包提供的FileUtils工具类进行删除try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {e.printStackTrace();}}// 创建根目录rootDir.mkdir();// ZipInputstream :用于进行zip格式的压缩文件输入流try (ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile))) {// 遍历压缩包中的每个子目录或子文件(ZipEntry类型的对象)ZipEntry zipEntry = null;while ((zipEntry = in.getNextEntry()) != null) {File file = new File(rootDir.getPath() + "\\" + zipEntry.getName());System.out.println(zipEntry.getName());if (zipEntry.isDirectory()) {// 子目录file.mkdir();} else {// 物理磁盘创建文件file.createNewFile();// 读取当前压缩包中的子文件,并通过输出流out写入子文件中FileOutputStream out = new FileOutputStream(file);byte[] buff = new byte[1024];int len = -1;while ((len = in.read(buff)) != -1) {out.write(buff, 0, len);}}}} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}// 解压缩rar格式public static void unrar(String path) {// 1.创建压缩rar格式File rarFile = new File(path);File rootDir = new File(rarFile.getParent() + "\\" + rarFile.getName().substring(0, rarFile.getName().lastIndexOf(".")));if (rootDir.exists()) {try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}rootDir.mkdir();// 创建Archive 对象,用于读取rar压缩文件格式try (Archive archive = new Archive(new FileInputStream(path))) {// 获取压缩文件中的所有子目录或子文件(FIleHeader对象)List<FileHeader> fileheaderList = archive.getFileHeaders();// 按照子目录(子文件)名称排序fileheaderList.sort(new Comparator<FileHeader>() {@Overridepublic int compare(FileHeader o1, FileHeader o2) {return o1.getFileName().compareTo(o2.getFileName());}});// 遍历子目录和子文件for (FileHeader fd : fileheaderList) {System.out.println(fd.getFileName());File f = new File(rootDir.getPath() + "\\" + fd.getFileName());if (fd.isDirectory()) {// 创建新的子目录f.mkdir();} else {// 创建新的子文件f.createNewFile();// 获取压缩包中的子文件输入流InputStream in = archive.getInputStream(fd);// 复制文件输入流至新子文件FileUtils.copyInputStreamToFile(in, f);}}} catch (RarException | IOException e) {// TODO: handle exceptione.printStackTrace();}}}
写入zip包(压缩)
首先创建File对象files引用原始目录,然后创建一个ZipOutputStream,传入一FileOutputStream作为数据源,调用listFiles()方法,获取并遍历原始目录下的子文件列表,每次循环创建一个ZipEntry,每写入一个文件前,调用putNextEntry()方法,然后将原文件的字节内容,写入zip压缩包,需要注意,每次写完文件,必须调用closeEntry()结束当前ZipEntry。
public class Test05 {public static void main(String[] args) {//所在目录File dir=new File("D:\\1\\图片");//获取所有的原始文件File[] files=dir.listFiles();//创建zip压缩文件的输出流try(ZipOutputStream out=new ZipOutputStream(new FileOutputStream(dir.getPath()+"\\"+".zip"))){//遍历所有的原始文件for(File f:files) {//写入一个压缩包中的子文件(ZipEntry对象)out.putNextEntry(new ZipEntry(f.getName()));//写入字节内容out.write(Files.readAllBytes(f.toPath()));//关闭压缩包中的子文件out.closeEntry();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}