当前位置: 首页 > news >正文

如何通过 Java 来完成 zip 文件与 rar 文件的解压缩?

目录

一、用到的知识点

二、代码展示(分解版)

三、代码展示(整体版)


一、用到的知识点

1.IO流:

        Input:输入,通过“输入流”进行文件的读取操作

        Output:输出,通过“输出流”进行文件的写入操作

2.文件操作相关:

        File类:用于表示文件和目录的路径。

        FileInputStream和FileOutputStream:用于读取和写入文件。

3.压缩文件处理:

        ZipInputStream:用于读取 ZIP 压缩文件的输入流。

        ZipEntry:表示 ZIP 压缩文件中的条目(文件或目录)。

4.异常处理:

        FileNotFoundException:当尝试访问不存在的文件时抛出。

        IOException:用于处理输入输出操作中的一般性异常。

        RarException:处理与 RAR 压缩文件操作相关的特定异常。

5.数据输入输出流:

        InputStream:用于读取数据的输入流。

6.集合操作:

        List:用于存储文件头信息的列表。

7.比较器(Comparator):用于对文件头列表进行排序。

8.第三方库 commons-io 中的 FileUtils 类:(此jar包在文末)

       用于删除目录和复制输入流到文件。

二、代码展示(分解版)

步骤1:判断文件类型

  •         若是".zip"文件则调用unzip()方法来解压缩 ZIP 文件,若是".rar"文件则调用unrar()方法来解压缩 RAR 文件
//指定文件夹String Path = “D:\\...\\xxxx.zip”String Path = “D:\\...\\xxxx.rar”
}
//1.判断文件类型if(path.endsWith(".zip")) {unzip(path);}else if(path.endsWith(".rar")) {unrar(path);}	}

步骤2:定义unzip()方法

  • 根据输入的文件路径创建源文件对象。
  • 确定解压缩后的根目录路径,并创建对应的文件对象。
  • 如果根目录已存在,尝试删除(包括使用 FileUtils 工具类删除非空目录),然后重新创建根目录。
  • 创建用于读取 ZIP 格式的输入流。
  • 遍历压缩包中的每个条目(子文件或子目录)。
  • 为每个条目创建对应的文件对象。
  • 判断条目是子文件还是子目录,分别进行创建文件或目录的操作。
  • 对于子文件,创建输出流,读取输入流中的数据并写入子文件。
  • 处理可能出现的文件未找到和输入输出异常。
//2.解压缩zip格式public static void unzip(String path) {//(1)根据原始路径(字符串),创建源文件(File对象)File sourceFile = new File(path);//(2)根目录String sourceName = sourceFile.getName();File rootDir = new File(sourceFile.getParent()+"\\"+sourceName.substring(0,sourceName.lastIndexOf(".")));//(3)判断根目录是否已经存在if(rootDir.exists()) {//若存在,则删除rootDir.delete();//只能删除空目录//使用commons-io包提供的FileUtils工具类进行删除try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {e.printStackTrace();}}//(4)创建根目录rootDir.mkdir();//(5)ZipInputStream:用于进行zip格式的压缩输入流try {ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile));//(6)遍历压缩包中每个子文件子目录(zipEntry类型的对象)ZipEntry zipEntry = null;while((zipEntry = in.getNextEntry())!=null) {//(7)创建子文件子目录(File对象)File file = new File(rootDir.getPath()+"\\"+zipEntry.getName());//(8)判断是子文件还是子目录(不是子目录就是子文件)if(zipEntry.isDirectory()) {//物理磁盘创建子目录file.mkdir();}else {//物理磁盘创建子文件file.createNewFile();//(9)子文件的写入//读取当前压缩包的子文件,并通过输出流out写入新子文件中try (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 (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

 步骤3:定义unrar()方法

  • 根据输入的 RAR 文件路径创建根目录的文件对象。
  • 判断根目录是否存在,如果存在则尝试删除(使用 FileUtils 处理可能的异常),然后创建根目录。
  • 创建用于读取 RAR 压缩文件的 Archive 对象。
  • 获取压缩文件中的所有子目录和子文件的 FileHeader 对象,并存储在列表中。
  • 按照子目录和子文件的名称对列表进行排序。
  • 遍历列表中的每个 FileHeader 对象。
  • 根据 FileHeader 对象创建对应的文件对象。
  • 判断是子目录还是子文件,分别进行创建目录或文件的操作。
  • 对于子文件,获取输入流并使用 FileUtils 将输入流复制到子文件中。
  • 处理可能出现的 RAR 相关异常和输入输出异常。
//3.解压缩rar格式public static void unrar(String path) {//(1)创建解压缩的根目录File rarFile = new File(path);File rootDir = new File(rarFile.getParent()+"\\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));//(2)判断是否存在if(rootDir.exists()) {try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {e.printStackTrace();}}rootDir.mkdir();//(3)创建Archive对象,用于读取rar压缩文件格式try (Archive archive = new Archive(new FileInputStream(path))){//(4)获取压缩文件所有子目录子文件(FileHeader对象)List<FileHeader> fileheaderList = archive.getFileHeaders();//(5)按照子目录(子文件)名称排序fileheaderList.sort(new Comparator<FileHeader>() {@Overridepublic int compare(FileHeader o1, FileHeader o2) {return o1.getFileName().compareTo(o2.getFileName());}});//(6)遍历子目录子文件for(FileHeader fd : fileheaderList) {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) {e.printStackTrace();}}

三、代码展示(整体版)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Comparator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;import org.apache.commons.io.FileUtils;import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;public class Test {
//指定文件夹String Path = “D:\\...\\xxxx.zip”String Path = “D:\\...\\xxxx.rar”
}
//1.判断文件类型if(path.endsWith(".zip")) {unzip(path);}else if(path.endsWith(".rar")) {unrar(path);}	}//2.解压缩zip格式public static void unzip(String path) {//(1)根据原始路径(字符串),创建源文件(File对象)File sourceFile = new File(path);//(2)根目录String sourceName = sourceFile.getName();File rootDir = new File(sourceFile.getParent()+"\\"+sourceName.substring(0,sourceName.lastIndexOf(".")));//(3)判断根目录是否已经存在if(rootDir.exists()) {//若存在,则删除rootDir.delete();//只能删除空目录//使用commons-io包提供的FileUtils工具类进行删除try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {e.printStackTrace();}}//(4)创建根目录rootDir.mkdir();//(5)ZipInputStream:用于进行zip格式的压缩输入流try {ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile));//(6)遍历压缩包中每个子文件子目录(zipEntry类型的对象)ZipEntry zipEntry = null;while((zipEntry = in.getNextEntry())!=null) {//(7)创建子文件子目录(File对象)File file = new File(rootDir.getPath()+"\\"+zipEntry.getName());//(8)判断是子文件还是子目录(不是子目录就是子文件)if(zipEntry.isDirectory()) {//物理磁盘创建子目录file.mkdir();}else {//物理磁盘创建子文件file.createNewFile();//(9)子文件的写入//读取当前压缩包的子文件,并通过输出流out写入新子文件中try (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 (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//3.解压缩rar格式public static void unrar(String path) {//(1)创建解压缩的根目录File rarFile = new File(path);File rootDir = new File(rarFile.getParent()+"\\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));//(2)判断是否存在if(rootDir.exists()) {try {FileUtils.deleteDirectory(rootDir);} catch (IOException e) {e.printStackTrace();}}rootDir.mkdir();//(3)创建Archive对象,用于读取rar压缩文件格式try (Archive archive = new Archive(new FileInputStream(path))){//(4)获取压缩文件所有子目录子文件(FileHeader对象)List<FileHeader> fileheaderList = archive.getFileHeaders();//(5)按照子目录(子文件)名称排序fileheaderList.sort(new Comparator<FileHeader>() {@Overridepublic int compare(FileHeader o1, FileHeader o2) {return o1.getFileName().compareTo(o2.getFileName());}});//(6)遍历子目录子文件for(FileHeader fd : fileheaderList) {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) {e.printStackTrace();}}
}

四、使用场景

    以上提供了两种常见压缩格式(ZIP 和 RAR)文件的解压缩功能。通过判断输入文件的格式(根据文件扩展名),调用相应的解压缩方法(unzip 或 unrar),能够将压缩文件中的内容正确地解压到指定的目录中。

这种功能在很多场景中都非常有用,例如:

  1. 数据处理和分析:当获取到压缩形式的数据时,需要解压缩来获取原始数据进行处理和分析。
  2. 文件传输和存储:在文件传输或存储过程中,压缩可以节省空间和提高传输效率,到达目的地后再解压缩以恢复原始文件结构。
  3. 软件开发:在开发过程中,可能需要处理和整合来自不同来源的压缩文件资源。

        总的来说,这段代码提供了一种灵活且可复用的方式来处理 ZIP 和 RAR 压缩文件的解压缩操作,满足了在各种应用中对压缩文件进行处理的需求。

相关文章:

如何通过 Java 来完成 zip 文件与 rar 文件的解压缩?

目录 一、用到的知识点 二、代码展示(分解版) 三、代码展示(整体版) 一、用到的知识点 1.IO流&#xff1a; Input:输入&#xff0c;通过“输入流”进行文件的读取操作 Output:输出&#xff0c;通过“输出流”进行文件的写入操作 2.文件操作相关&#xff1a; File类&#xff…...

C 语言中的联合(Union)的用途是什么?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; &#x1f4d9;C 语言百万年薪修炼课程 通俗易懂&#xff0c;深入浅出&#xff0c;匠心打磨&#xff0c;死磕细节&#xff0c;6年迭代&#xff0c;看过的人都说好。 文章目…...

汽车电子助力转向系统研究

汽车电子助力转向系统研究 摘要 电子助力转向系统&#xff08;Electric Power Steering&#xff0c;EPS&#xff09;是一种利用电动机辅助驾驶员进行车辆转向的系统。相比于传统的液压助力转向系统&#xff0c;EPS具有更高的效率、精确性和可控性。本文将详细探讨EPS的工作原理…...

大数据学习之 scala基础(补充)

scala基础&#xff1a; hello world: 写scala可运行文件的注意事项1、如果一个scala文件要运行&#xff0c;class要改成object2、如果是class&#xff0c;就仅单纯代表一个类&#xff0c;如果是object代表的是单例对象3、scala语法中&#xff0c;一句话结束不需要加分号4、sca…...

正向传播和反向传播

正向传播&#xff08;Forward Propagation&#xff09; 正向传播是指将输入数据通过神经网络&#xff0c;计算出预测值的过程。具体步骤如下&#xff1a; 输入层&#xff1a;接受输入数据。隐藏层&#xff1a;每个隐藏层中的神经元接收上一层的输出&#xff0c;进行加权求和&…...

前端文件下载的方式

方式一&#xff1a;a标签直接下载 <a href"链接" >下载</a>一个文件链接&#xff08;一般是服务器上的某个文件&#xff09;&#xff0c;这个链接一般地址栏输入是预览&#xff0c;不是附件下载 如果想改成附件下载&#xff0c;以下两种方式任选一个均…...

视图库对接系列(GA-T 1400)十六、视图库对接系列(本级)通知(订阅回调)

说明 之前我们实现了订阅接口,其中有一个receiveAddr参数, 这个就是对应的回调的地址。一般情况下对应的是同一个服务。 我们推荐使用http://xxx:xxx/VIID/SubscribeNotifications接口文档 SubscribeNotificationList对象对象如下: 文档中是xml,但实际上目前使用的都是jso…...

Python | Leetcode Python题解之第230题二叉搜索树中第K小的元素

题目&#xff1a; 题解&#xff1a; class AVL:"""平衡二叉搜索树&#xff08;AVL树&#xff09;&#xff1a;允许重复值"""class Node:"""平衡二叉搜索树结点"""__slots__ ("val", "parent&quo…...

Python酷库之旅-第三方库Pandas(018)

目录 一、用法精讲 44、pandas.crosstab函数 44-1、语法 44-2、参数 44-3、功能 44-4、返回值 44-5、说明 44-6、用法 44-6-1、数据准备 44-6-2、代码示例 44-6-3、结果输出 45、pandas.cut函数 45-1、语法 45-2、参数 45-3、功能 45-4、返回值 45-5、说明 4…...

九科bit-Worker RPA 内容学习

入门阶段&#xff0c; 花时间学习和记忆细枝末节&#xff0c;可能会反而分散新手去理解核心逻辑的精力&#xff0c;并且不常用的知识也很容易被遗忘。 简介&#xff1a; 什么是RPA&#xff1f; RPA&#xff08;Robotic Process Automation&#xff0c;机器人流程自动化&#x…...

vscode编译环境配置-golang

1. 支持跳转 如果单测函数上方不显示run test | debug test&#xff0c;需要安装Code Debugger&#xff08;因为以前的go Test Explorer不再被维护了&#xff09; 2. 单测 指定单个用例测试 go test -v run TestXXXdlv 调试 需要安装匹配的go版本和delve版本&#xff08;如…...

【JavaEE】网络编程——UDP

&#x1f921;&#x1f921;&#x1f921;个人主页&#x1f921;&#x1f921;&#x1f921; &#x1f921;&#x1f921;&#x1f921;JavaEE专栏&#x1f921;&#x1f921;&#x1f921; 文章目录 1.数据报套接字(UDP)1.1特点1.2编码1.2.1DatagramSocket1.2.2DatagramPacket…...

JAVA毕业设计147—基于Java+Springboot的手机维修管理系统(源代码+数据库)

基于JavaSpringboot的手机维修管理系统(源代码数据库)147 一、系统介绍 本项目分为用户、管理员、维修员三种角色 1、用户&#xff1a; 注册、登录、新闻公告、售后申请、申请列表、意见反馈、个人信息、密码修改 2、管理员&#xff1a; 用户管理、用户管理、栏目管理、网…...

力扣第228题“汇总区间”

在本篇文章中&#xff0c;我们将详细解读力扣第228题“汇总区间”。通过学习本篇文章&#xff0c;读者将掌握如何遍历和汇总区间&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力扣第228题“汇总区间”描…...

部署大语言模型并对话

在阿里云的https://developer.aliyun.com/adc/scenario/b105013328814fe995c0f091d708d67d 选择函数计算 设置服务器配置 复制公网地址 这个地址不能直接 在返回应用&#xff0c;创建应用LLM 对话页面 Open WebUI 点击下面的创建应用 部署完成后访问域名 打开访问地址...

WebSocket、socket.io-client

WebSocket WebSocket 是一种网络通信协议&#xff0c;它提供了一个在单个长期持久的 TCP 连接上进行全双工&#xff08;full-duplex&#xff09;通信的通道。 WebSocket 允许客户端和服务器之间进行双向的数据交换&#xff0c;这意味着服务器可以主动向客户端推送数据&#x…...

Maven 仓库

在 Maven 世界中&#xff0c;任何一个依赖、插件或者项目构建的输出&#xff0c;都可以称为 构件 。 坐标和依赖是构件在 Maven 世界中的逻辑表示方式&#xff0c;构件的物理表示方式是文件&#xff0c;Maven 通过仓库来统一管理这些文件。 任何一个构件都有一组坐标唯一标识。…...

给后台写了一个优雅的自定义风格的数据日志上报页面

highlight: atelier-cave-dark 查看后台数据日志是非常常见的场景,经常看到后台的小伙伴从服务器日志复制一段json数据字符串,然后找一个JSON工具网页打开,在线JSON格式化校验。有的时候,一些业务需要展示mqtt或者socket的实时信息展示,如果不做任何修改直接展示一串字符…...

【React Native优质开源项目】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…...

Android 自动更新时间的数字时钟 TextClock

TextClock 继承 TextView &#xff0c;使用方法和 TextView 一样。 它专门用于显示数字时钟&#xff0c;可以自定义显示格式。 只要在布局文件里添加&#xff0c;它会自动更新时间&#xff0c;不需要添加刷新逻辑。 布局文件&#xff0c; <?xml version"1.0"…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...