java打包文件成zip、压缩文件及file.mkdir和mkdirs的区别详解
作者:小学鸡!
一、file.mkdir 和 mkdirs 的区别
在 Java 中,File
类提供了两个方法用于创建目录:mkdir()
和 mkdirs()
。它们的作用有一些关键区别:
① file.mkdir()
创建单级目录。
当有多层目录时,只有在父目录已存在的情况下,才能创建最后的目录。
假如只有一层目录,则可以创建。
返回
true
表示目录创建成功,返回false
表示创建失败(例如,如果父目录不存在或目录已存在)。
② file.mkdirs()
创建多级目录,包括不存在的父目录。
如果任何中间目录不存在,
mkdirs()
会递归创建所有必要的父目录。返回值:返回
true
表示目录及其父目录创建成功,返回false
表示创建失败。
举例:
File dir = new File("C:\\parentDir\\subDir\\newDir"); boolean created = dir.mkdir(); // 如果 parentDir 或 subDir 不存在,则创建失败 boolean created = dir.mkdirs(); // 会创建 parentDir 和 subDir,如果它们不存在
二、文件打包成zip
Java 提供了丰富的标准库用于处理 ZIP 文件,其中最主要的是 java.util.zip
包。该包包含了一系列类和接口,用于创建、读取和操作 ZIP 文件。常用的类包括:
ZipInputStream
和ZipOutputStream
:用于顺序读取和写入 ZIP 文件。ZipFile
和ZipEntry
:用于随机访问 ZIP 文件中的条目。
1. 压缩单个文件
在 Java 中实现文件打包成 zip 的过程可以分为以下几个步骤:
创建一个 ZipOutputStream 对象 ---- 使用 ZipEntry 将文件添加到 zip 包中 ---- 将文件内容写入到 ZipOutputStream 中 ---- 关闭 ZipOutputStream 对象
示例:将桌面上的 12.txt 打包成 zip
public class Test { public static void main(String[] args) { //文件所在的位置 String filePath = "C:\\Users\\ASUS\\Desktop\\12.txt"; //压缩后文件存放的位置 String zipFilePath = "C:\\Users\\ASUS\\Desktop\\12.zip"; //使用try-with-resources语句来确保流在使用后正确关闭 try ( FileInputStream fileInputStream = new FileInputStream(filePath); //创建ZipOutputStream对象 FileOutputStream fileOutputStream = new FileOutputStream(zipFilePath); ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream) ) { //使用ZipEntry将文件添加到zip包中:表示要添加到zip包中的文件名为"12.txt" ZipEntry zipEntry = new ZipEntry("12.txt"); zipOutputStream.putNextEntry(zipEntry); //将文件内容写入到ZipOutputStream中 byte[] buffer = new byte[1024]; int len; while ((len = fileInputStream.read(buffer)) != -1) { zipOutputStream.write(buffer, 0, len); } zipOutputStream.closeEntry(); } catch (Exception e) { e.printStackTrace(); } } }
注意:
① zipOutputStream.closeEntry()
:用来关闭当前正在写入的 ZipEntry
,表示结束这个条目(条目:文件或文件夹)的写入过程。
zipOutputStream.close()
:在 try-with-resources
结束时自动调用,是关闭整个 ZipOutputStream
,释放资源。
② ZipEntry
中指定的应该是 ZIP 文件内部的文件名,而不是完整路径。若是完整路径(ZipEntry zipEntry = new ZipEntry("C:\\Users\\ASUS\\Desktop\\12.txt")
),这可能导致 ZIP 包内部出现意料之外的文件结构:
2. 压缩多个文件和文件夹
案例:现在有个文件,样式为下图,需要压缩。
按照正常思路就是遍历文件夹:
public class Test { public static void main(String[] args) { //文件位置 String filePath = "C:\\Users\\ASUS\\Desktop\\11"; //输出位置 String zipFilePath = "C:\\Users\\ASUS\\Desktop\\11.zip"; try ( FileOutputStream fos = new FileOutputStream(zipFilePath); ZipOutputStream zos = new ZipOutputStream(fos) ) { //创建文件对象 File file = new File(filePath); //调方法:开始递归添加文件和文件夹 zipFile(file, file.getName(), zos); } catch (Exception e) { e.printStackTrace(); } } public static void zipFile(File file, String fileName, ZipOutputStream zos) { if (file.isDirectory()) { File[] children = file.listFiles(); for (File child : children) { zipFile(child, child.getName(), zos); } } try ( FileInputStream fileInputStream = new FileInputStream(file) ) { ZipEntry zipEntry = new ZipEntry(fileName); zos.putNextEntry(zipEntry); byte[] buffer = new byte[1024]; int len; while ((len = fileInputStream.read(buffer)) != -1) { zos.write(buffer, 0, len); } zos.closeEntry(); } catch (Exception e) { e.printStackTrace(); } } }
问题:只是压缩了文件,原本的目录结构没有保留,如下:
解决:
public class Test { public static void main(String[] args) { //文件位置 String filePath = "C:\\Users\\ASUS\\Desktop\\11"; //输出位置 String zipFilePath = "C:\\Users\\ASUS\\Desktop\\11.zip"; try ( FileOutputStream fos = new FileOutputStream(zipFilePath); ZipOutputStream zos = new ZipOutputStream(fos) ) { //创建文件对象 File file = new File(filePath); //调方法:开始递归添加文件和文件夹 //file.getName:获取文件名,包括文件名后缀 zipFile(file, file.getName(), zos); } catch (Exception e) { e.printStackTrace(); } } public static void zipFile(File file, String fileName, ZipOutputStream zos) { if (file.isDirectory()) { /* 假如是个空文件夹,下面这个: zos.putNextEntry(new ZipEntry(fileName + "/")); 就是为了保留空文件夹 */ try { zos.putNextEntry(new ZipEntry(fileName + "/")); zos.closeEntry(); } catch (Exception e) { e.printStackTrace(); } File[] children = file.listFiles(); //确保目录不是空的 if (children != null) { for (File child : children) { //加 fileName + "/" 是为了保留原始的目录结构 zipFile(child, fileName + "/" + child.getName(), zos); } } return; } try ( FileInputStream fileInputStream = new FileInputStream(file) ) { ZipEntry zipEntry = new ZipEntry(fileName); zos.putNextEntry(zipEntry); byte[] buffer = new byte[1024]; int len; while ((len = fileInputStream.read(buffer)) != -1) { zos.write(buffer, 0, len); } zos.closeEntry(); } catch (Exception e) { e.printStackTrace(); } } }
代码分析:
① 为什么是/
,而不是\
?
在 ZIP 文件的规范中,路径分隔符始终使用正斜杠 /
,而不是反斜杠 \
② 为什么 return?
否则会报错:java.io.FileNotFoundException: C:\Users\ASUS\Desktop\11\22\33 (拒绝访问)
,因为 FileInputStream
只能用于读取文件,而不能用于读取目录。如果代码试图将目录作为 FileInputStream
的输入,会报 FileNotFoundException
。
因为是递归调用,但递归结束时,开始返回调用栈,调用并继续执行剩余的代码(所以会报错,涉及到递归调用的逻辑)
总结
到此这篇关于java打包文件成zip、压缩文件及file.mkdir和mkdirs的区别详解的文章就介绍到这了,更多相关java打包文件成zip压缩文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!