Technology Sharing

How to decompress zip and rar files using Java?

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Table of contents

1. Knowledge points used

2. Code display (decomposed version)

3. Code display (overall version)


1. Knowledge points used

1.IO stream:

Input: Input, read files through the "input stream"

Output: Output, write files through the "output stream"

2. File operation related:

File class: used to represent paths to files and directories.

FileInputStream and FileOutputStream: used to read and write files.

3. Compressed file processing:

ZipInputStream: An input stream used to read ZIP compressed files.

ZipEntry: Represents an entry (file or directory) in a ZIP compressed file.

4. Exception handling:

FileNotFoundException: Thrown when trying to access a file that does not exist.

IOException: Used to handle general exceptions in input and output operations.

RarException: Handles specific exceptions related to RAR archive operations.

5. Data input and output flow:

InputStream: Input stream used to read data.

6. Collection operations:

List: A list used to store file header information.

7. Comparator:Used to sort the file header list.

8. FileUtils class in the third-party library commons-io:(This jar package is at the end of the article)

Used to delete directories and copy input streams to files.

2. Code display (decomposed version)

Step 1: Determine the file type

  • If it is a ".zip" file, the unzip() method is called to decompress the ZIP file. If it is a ".rar" file, the unrar() method is called to decompress the RAR file.
  1. //指定文件夹
  2. String Path = “D:\...\xxxx.zip”
  3. String Path = “D:\...\xxxx.rar”
  4. }
  5. //1.判断文件类型
  6. if(path.endsWith(".zip")) {
  7. unzip(path);
  8. }else if(path.endsWith(".rar")) {
  9. unrar(path);
  10. }
  11. }

Step 2: Define the unzip() method

  • Create a source file object based on the input file path.
  • Determine the root directory path after decompression and create the corresponding file object.
  • If the root directory already exists, try deleting it (including usingFileUtilsTools class to delete non-empty directories) and then recreate the root directory.
  • Creates an input stream for reading the ZIP format.
  • Iterate over each entry (subfile or subdirectory) in the archive.
  • For each entry, a corresponding file object is created.
  • Determine whether the entry is a subfile or subdirectory, and create the file or directory respectively.
  • For a subfile, create an output stream, read the data from the input stream and write it to the subfile.
  • Handle possible file not found and input and output exceptions.
  1. //2.解压缩zip格式
  2. public static void unzip(String path) {
  3. //(1)根据原始路径(字符串),创建源文件(File对象)
  4. File sourceFile = new File(path);
  5. //(2)根目录
  6. String sourceName = sourceFile.getName();
  7. File rootDir = new File(sourceFile.getParent()+"\"+sourceName.substring(0,sourceName.lastIndexOf(".")));
  8. //(3)判断根目录是否已经存在
  9. if(rootDir.exists()) {
  10. //若存在,则删除
  11. rootDir.delete();//只能删除空目录
  12. //使用commons-io包提供的FileUtils工具类进行删除
  13. try {
  14. FileUtils.deleteDirectory(rootDir);
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. //(4)创建根目录
  20. rootDir.mkdir();
  21. //(5)ZipInputStream:用于进行zip格式的压缩输入流
  22. try {
  23. ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile));
  24. //(6)遍历压缩包中每个子文件子目录(zipEntry类型的对象)
  25. ZipEntry zipEntry = null;
  26. while((zipEntry = in.getNextEntry())!=null) {
  27. //(7)创建子文件子目录(File对象)
  28. File file = new File(rootDir.getPath()+"\"+zipEntry.getName());
  29. //(8)判断是子文件还是子目录(不是子目录就是子文件)
  30. if(zipEntry.isDirectory()) {
  31. //物理磁盘创建子目录
  32. file.mkdir();
  33. }else {
  34. //物理磁盘创建子文件
  35. file.createNewFile();
  36. //(9)子文件的写入
  37. //读取当前压缩包的子文件,并通过输出流out写入新子文件中
  38. try (FileOutputStream out = new FileOutputStream(file)) {
  39. byte[] buff = new byte[1024];
  40. int len = -1;
  41. while((len = in.read(buff))!=-1) {
  42. out.write(buff,0,len);
  43. }
  44. }
  45. }
  46. }
  47. } catch (FileNotFoundException e) {
  48. e.printStackTrace();
  49. } catch (IOException e) {
  50. e.printStackTrace();
  51. }
  52. }

Step 3: Define the unrar() method

  • Creates a file object for the root directory according to the input RAR file path.
  • Determine whether the root directory exists, and if so, try to delete it (usingFileUtilsHandle possible exceptions), and then create the root directory.
  • Create a program for reading RAR archivesArchiveobject.
  • Get all subdirectories and subfiles in the compressed fileFileHeaderobjects and store them in a list.
  • Sort the list by the names of the subdirectories and subfiles.
  • Iterate through eachFileHeaderobject.
  • according toFileHeaderObject creates the corresponding file object.
  • Determine whether it is a subdirectory or a subfile, and create the directory or file respectively.
  • For subfiles, get the input stream and useFileUtilsCopies the input stream into a subfile.
  • Handle possible RAR-related exceptions and input/output exceptions.
  1. //3.解压缩rar格式
  2. public static void unrar(String path) {
  3. //(1)创建解压缩的根目录
  4. File rarFile = new File(path);
  5. File rootDir = new File(rarFile.getParent()+"\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));
  6. //(2)判断是否存在
  7. if(rootDir.exists()) {
  8. try {
  9. FileUtils.deleteDirectory(rootDir);
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. rootDir.mkdir();
  15. //(3)创建Archive对象,用于读取rar压缩文件格式
  16. try (Archive archive = new Archive(new FileInputStream(path))){
  17. //(4)获取压缩文件所有子目录子文件(FileHeader对象)
  18. List<FileHeader> fileheaderList = archive.getFileHeaders();
  19. //(5)按照子目录(子文件)名称排序
  20. fileheaderList.sort(new Comparator<FileHeader>() {
  21. @Override
  22. public int compare(FileHeader o1, FileHeader o2) {
  23. return o1.getFileName().compareTo(o2.getFileName());
  24. }
  25. });
  26. //(6)遍历子目录子文件
  27. for(FileHeader fd : fileheaderList) {
  28. File f = new File(rootDir.getPath()+"\"+fd.getFileName());
  29. if(fd.isDirectory()) {
  30. //物理磁盘创建子目录
  31. f.mkdir();
  32. }else {
  33. //物理磁盘创建子文件
  34. f.createNewFile();
  35. //获取压缩包中子文件输入流
  36. InputStream in = archive.getInputStream(fd);
  37. //复制文件输入流至子文件
  38. FileUtils.copyInputStreamToFile(in, f);
  39. }
  40. }
  41. } catch (RarException | IOException e) {
  42. e.printStackTrace();
  43. }
  44. }

3. Code display (overall version)

  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.util.Comparator;
  8. import java.util.List;
  9. import java.util.zip.ZipEntry;
  10. import java.util.zip.ZipInputStream;
  11. import org.apache.commons.io.FileUtils;
  12. import com.github.junrar.Archive;
  13. import com.github.junrar.exception.RarException;
  14. import com.github.junrar.rarfile.FileHeader;
  15. public class Test {
  16. //指定文件夹
  17. String Path = “D:\...\xxxx.zip”
  18. String Path = “D:\...\xxxx.rar”
  19. }
  20. //1.判断文件类型
  21. if(path.endsWith(".zip")) {
  22. unzip(path);
  23. }else if(path.endsWith(".rar")) {
  24. unrar(path);
  25. }
  26. }
  27. //2.解压缩zip格式
  28. public static void unzip(String path) {
  29. //(1)根据原始路径(字符串),创建源文件(File对象)
  30. File sourceFile = new File(path);
  31. //(2)根目录
  32. String sourceName = sourceFile.getName();
  33. File rootDir = new File(sourceFile.getParent()+"\"+sourceName.substring(0,sourceName.lastIndexOf(".")));
  34. //(3)判断根目录是否已经存在
  35. if(rootDir.exists()) {
  36. //若存在,则删除
  37. rootDir.delete();//只能删除空目录
  38. //使用commons-io包提供的FileUtils工具类进行删除
  39. try {
  40. FileUtils.deleteDirectory(rootDir);
  41. } catch (IOException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. //(4)创建根目录
  46. rootDir.mkdir();
  47. //(5)ZipInputStream:用于进行zip格式的压缩输入流
  48. try {
  49. ZipInputStream in = new ZipInputStream(new FileInputStream(sourceFile));
  50. //(6)遍历压缩包中每个子文件子目录(zipEntry类型的对象)
  51. ZipEntry zipEntry = null;
  52. while((zipEntry = in.getNextEntry())!=null) {
  53. //(7)创建子文件子目录(File对象)
  54. File file = new File(rootDir.getPath()+"\"+zipEntry.getName());
  55. //(8)判断是子文件还是子目录(不是子目录就是子文件)
  56. if(zipEntry.isDirectory()) {
  57. //物理磁盘创建子目录
  58. file.mkdir();
  59. }else {
  60. //物理磁盘创建子文件
  61. file.createNewFile();
  62. //(9)子文件的写入
  63. //读取当前压缩包的子文件,并通过输出流out写入新子文件中
  64. try (FileOutputStream out = new FileOutputStream(file)) {
  65. byte[] buff = new byte[1024];
  66. int len = -1;
  67. while((len = in.read(buff))!=-1) {
  68. out.write(buff,0,len);
  69. }
  70. }
  71. }
  72. }
  73. } catch (FileNotFoundException e) {
  74. e.printStackTrace();
  75. } catch (IOException e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. //3.解压缩rar格式
  80. public static void unrar(String path) {
  81. //(1)创建解压缩的根目录
  82. File rarFile = new File(path);
  83. File rootDir = new File(rarFile.getParent()+"\"+rarFile.getName().substring(0,rarFile.getName().lastIndexOf(".")));
  84. //(2)判断是否存在
  85. if(rootDir.exists()) {
  86. try {
  87. FileUtils.deleteDirectory(rootDir);
  88. } catch (IOException e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. rootDir.mkdir();
  93. //(3)创建Archive对象,用于读取rar压缩文件格式
  94. try (Archive archive = new Archive(new FileInputStream(path))){
  95. //(4)获取压缩文件所有子目录子文件(FileHeader对象)
  96. List<FileHeader> fileheaderList = archive.getFileHeaders();
  97. //(5)按照子目录(子文件)名称排序
  98. fileheaderList.sort(new Comparator<FileHeader>() {
  99. @Override
  100. public int compare(FileHeader o1, FileHeader o2) {
  101. return o1.getFileName().compareTo(o2.getFileName());
  102. }
  103. });
  104. //(6)遍历子目录子文件
  105. for(FileHeader fd : fileheaderList) {
  106. File f = new File(rootDir.getPath()+"\"+fd.getFileName());
  107. if(fd.isDirectory()) {
  108. //物理磁盘创建子目录
  109. f.mkdir();
  110. }else {
  111. //物理磁盘创建子文件
  112. f.createNewFile();
  113. //获取压缩包中子文件输入流
  114. InputStream in = archive.getInputStream(fd);
  115. //复制文件输入流至子文件
  116. FileUtils.copyInputStreamToFile(in, f);
  117. }
  118. }
  119. } catch (RarException | IOException e) {
  120. e.printStackTrace();
  121. }
  122. }
  123. }

4. Usage scenarios

The above provides two common compression formats (ZIP and RAR) file decompression functions. By judging the format of the input file (based on the file extension), calling the corresponding decompression method (unziporunrar), can correctly decompress the contents of the compressed file into the specified directory.

This feature is very useful in many scenarios, such as:

  1. Data processing and analysis: When data is obtained in compressed form, it needs to be decompressed to obtain the original data for processing and analysis.
  2. File transfer and storage: During file transfer or storage, compression can save space and improve transmission efficiency. After reaching the destination, the file can be decompressed to restore the original file structure.
  3. Software Development: During the development process, you may need to process and integrate compressed file resources from different sources.

In general, this code provides a flexible and reusable way to handle the decompression operation of ZIP and RAR compressed files, meeting the needs of processing compressed files in various applications.