Java解压rar5兼容rar4

cnblogs 2024-07-31 08:09:01 阅读 68

RAR文件格式由WinRAR开发,广泛用于文件压缩和归档。随着技术的发展,RAR5作为更新的版本,引入了多项改进以提高压缩效率和数据安全性。

    <li> 压缩效率:RAR5通过增大字典大小至32MB,相较于RAR4的4MB,能够更有效地找到数据中的重复模式,从而提高压缩率,特别是在处理大型文件时。
  • 安全性增强:RAR5采用的256位AES加密算法,提供了更高级别的数据保护,相较于RAR4的加密标准,更难被破解。
  • 时间戳的国际化:RAR5使用UTC时间,解决了RAR4使用本地时间可能导致的时区混淆问题,使得文件的时间戳在全球范围内保持一致性。
  • 兼容性考虑:RAR5的格式较新,可能不被旧版本的解压软件识别。在需要确保最大兼容性的场景下,可能仍需使用RAR4格式。
  • 恢复卷的改进:RAR5格式支持的恢复卷数量大大增加,从RAR4的255个增加到65535个,这在处理多卷压缩文件时提供了更高的灵活性和容错性。
  • 错误纠正能力:RAR5的恢复记录基于Reed-Solomon错误纠正码,显著提高了压缩文件在受损情况下的自我修复能力。
  • 日志文件编码:RAR5使用UTF-16小端字节序编码,确保了日志文件中Unicode字符的正确存储和显示,提高了对国际化文件名的支持。

RAR5的Java解压实现

在Java中实现RAR5文件的解压,可以借助java-unrarSevenZipJBinding库。以下是具体的实现步骤和代码示例。

1、添加依赖:在项目的pom.xml文件中添加相关依赖。

<dependency>

<groupId>com.github.axet</groupId>

<artifactId>java-unrar</artifactId>

<version>1.7.0-8</version>

</dependency>

<dependency>

<groupId>net.sf.sevenzipjbinding</groupId>

<artifactId>sevenzipjbinding</artifactId>

<version>16.02-2.01</version>

</dependency>

<dependency>

<groupId>net.sf.sevenzipjbinding</groupId>

<artifactId>sevenzipjbinding-all-platforms</artifactId>

<version>16.02-2.01</version>

</dependency>

2、编写解压工具类:创建Rar5DocExtractor类,实现解压逻辑。

1 package rar5;

2

3 import net.sf.sevenzipjbinding.*;

4 import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;

5

6 import java.io.*;

7 import java.util.*;

8

9 public class Rar5DocExtractor {

10

11 public List<File> extractFiles(File rarFile, File outputDir) throws IOException {

12 Set<File> extractedFiles = new HashSet<>();

13 if (!outputDir.exists()) {

14 outputDir.mkdirs(); // 确保输出目录存在

15 }

16

17 RandomAccessFile randomAccessFile = null;

18 IInArchive inArchive = null;

19 try {

20 randomAccessFile = new RandomAccessFile(rarFile, "r");

21 inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));

22 int[] in = new int[inArchive.getNumberOfItems()];

23 for (int i = 0; i < in.length; i++) {

24 in[i] = i;

25 }

26 inArchive.extract(in, false, new ExtractCallback(inArchive, outputDir.getAbsolutePath(), extractedFiles));

27 } finally {

28 if (randomAccessFile != null) {

29 randomAccessFile.close();

30 }

31 if (inArchive != null) {

32 try {

33 inArchive.close();

34 } catch (SevenZipException e) {

35 e.printStackTrace();

36 }

37 }

38 }

39 List<File> list=new ArrayList<>(extractedFiles);

40 return list;

41 }

42

43 private static class ExtractCallback implements IArchiveExtractCallback {

44 private IInArchive inArchive;

45 private String outDir;

46 private Set<File> extractedFiles;

47 // 用于跟踪是否需要关闭流的变量

48 private OutputStream fos = null;

49 private boolean closeStreamAfterOperation = false; // 标记流是否需要关闭

50

51 public ExtractCallback(IInArchive inArchive, String outDir, Set<File> extractedFiles) {

52 this.inArchive = inArchive;

53 this.outDir = outDir;

54 this.extractedFiles = extractedFiles;

55 }

56

57 @Override

58 public void setCompleted(long arg0) throws SevenZipException {

59 }

60

61 @Override

62 public void setTotal(long arg0) throws SevenZipException {

63 }

64

65

66 @Override

67 public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {

68 final String path = (String) inArchive.getProperty(index, PropID.PATH);

69 // 这里不再创建 File 对象,避免多次调用 getStream 时重复创建

70 return new ISequentialOutStream() {

71 public int write(byte[] data) throws SevenZipException {

72 File file = new File(outDir, path);

73 try {

74 if (data.length == 0) return 0;

75 file.getParentFile().mkdirs(); // 确保目录存在

76 if (fos == null) { // 如果这是第一次写入,初始化输出流

77 fos = new FileOutputStream(file);

78 closeStreamAfterOperation = true; // 设置标记,表示需要在操作结果后关闭流

79 }

80 fos.write(data);

81 fos.flush(); // 刷新以确保数据被写入磁盘

82 extractedFiles.add(file); // 添加到提取文件集合

83 } catch (IOException e) {

84 throw new SevenZipException("Error writing data to file: " + path, e);

85 }

86 return data.length;

87 }

88 };

89 }

90

91 @Override

92 public void prepareOperation(ExtractAskMode arg0) throws SevenZipException {

93 }

94

95 @Override

96 public void setOperationResult(ExtractOperationResult extractOperationResult) throws SevenZipException {

97 if (closeStreamAfterOperation && fos != null) {

98 try {

99 // 关闭输出流

100 fos.close();

101 } catch (IOException e) {

102 throw new SevenZipException("关闭文件输出流时报错", e);

103 } finally {

104 // 重置标记

105 closeStreamAfterOperation = false;

106 // 清除引用,以便垃圾回收

107 fos = null;

108 }

109 }

110 }

111

112 }

113 }

3、编写测试类:创建测试类以验证RAR5文件的解压功能。

1 package rar5;

2

3 import java.io.File;

4 import java.io.IOException;

5 import java.util.List;

6

7 public class RAR5ExtractorTest {

8

9 public static void main(String[] args) {

10 File rarDirFile = new File("src/main/resources/rar5Test06.rarbak");

11 File outDirFile = new File("src/main/resources/temp/rar5Test06.rar");

12

13 Rar5DocExtractor extractor = new Rar5DocExtractor();

14 try {

15 List<File> extractedFiles = extractor.extractFiles(rarDirFile, outDirFile);

16 System.out.println("Extracted files:");

17 for (File file : extractedFiles) {

18 System.out.println(file.getAbsolutePath());

19 }

20 } catch (IOException e) {

21 e.printStackTrace();

22 }

23 }

24 }



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。