java打包文件成zip、压缩文件及file.mkdir和mkdirs的区别详解

 更新时间:2024年12月25日 09:11:42   作者:小学鸡!  
这篇文章主要给大家介绍了关于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压缩文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JAVA读取PDF、WORD文档实例代码

    JAVA读取PDF、WORD文档实例代码

    本篇文章主要通过实例代码介绍了JAVA读取PDF、WORD文档,需要的朋友可以参考下
    2017-04-04
  • scala当中的文件操作和网络请求的实现方法

    scala当中的文件操作和网络请求的实现方法

    这篇文章主要介绍了scala当中的文件操作和网络请求的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • java实现dijkstra最短路径寻路算法

    java实现dijkstra最短路径寻路算法

    这篇文章主要为大家详细介绍了java实现dijkstra最短路径寻路算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Spring5路径匹配器PathPattern解析

    Spring5路径匹配器PathPattern解析

    这篇文章主要介绍了Spring5路径匹配器PathPattern,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java中创建对象的6种方式

    Java中创建对象的6种方式

    大家好,本篇文章主要讲的是Java中创建对象的6种方式,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下的相关资料
    2022-02-02
  • Java 获取Zookeeper节点下所有数据详细步骤

    Java 获取Zookeeper节点下所有数据详细步骤

    本文介绍了如何使用Java获取ZooKeeper节点下所有数据,实际应用示例中,我们演示了如何从ZooKeeper节点下获取配置信息并输出到控制台,ZooKeeper是一个开源的分布式协调服务,适用于分布式系统中的数据同步、配置管理、命名服务等功能,感兴趣的朋友一起看看吧
    2024-11-11
  • Mybatis实现动态建表代码实例

    Mybatis实现动态建表代码实例

    这篇文章主要介绍了Mybatis实现动态建表代码实例,解释一下,就是指根据传入的表名,动态地创建数据库表,以供后面的业务场景使用,
    而使用 Mybatis 的动态 SQL,就能很好地为我们解决这个问题,需要的朋友可以参考下
    2023-10-10
  • J2EE Servlet基础在浏览器上运行HelloServlet的方法

    J2EE Servlet基础在浏览器上运行HelloServlet的方法

    这篇文章主要介绍了J2EE Servlet基础在浏览器上运行HelloServlet的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Python单元测试_使用装饰器实现测试跳过和预期故障的方法

    Python单元测试_使用装饰器实现测试跳过和预期故障的方法

    下面小编就为大家带来一篇Python单元测试_使用装饰器实现测试跳过和预期故障的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Java实现图形化界面的日历

    Java实现图形化界面的日历

    这篇文章主要介绍了Java实现图形化界面的日历,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06

最新评论