How to Extract RAR5 Archives in Java Using java-unrar and SevenZipJBinding
This article explains the improvements of the RAR5 archive format over RAR4 and provides a step‑by‑step guide, including Maven dependencies and full Java source code, for extracting RAR5 files using the java‑unrar and SevenZipJBinding libraries.
RAR5 is the newer version of the RAR archive format developed by WinRAR, offering higher compression efficiency, stronger encryption, UTC timestamps, expanded recovery volumes, Reed‑Solomon error correction, and UTF‑16LE log encoding.
Compression efficiency: dictionary size increased to 32 MB (vs 4 MB in RAR4), improving compression ratios for large files.
Security: uses 256‑bit AES encryption, making data harder to crack.
Internationalized timestamps: UTC time eliminates timezone confusion.
Compatibility: older extraction tools may not recognize RAR5, so RAR4 may still be needed for maximum compatibility.
Recovery volume improvement: supports up to 65 535 recovery volumes (vs 255 in RAR4).
Error correction: Reed‑Solomon codes enhance self‑repair of damaged archives.
Log file encoding: UTF‑16LE ensures correct storage of Unicode characters and better support for international filenames.
Java implementation of RAR5 extraction
1. Add Maven dependencies for java-unrar and SevenZipJBinding:
<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. Create the Rar5DocExtractor class that opens the archive with SevenZip, iterates over items, and writes extracted files to the output directory.
package rar5;
import net.sf.sevenzipjbinding.*;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import java.io.*;
import java.util.*;
public class Rar5DocExtractor {
public List<File> extractFiles(File rarFile, File outputDir) throws IOException {
Set<File> extractedFiles = new HashSet<>();
if (!outputDir.exists()) {
outputDir.mkdirs();
}
RandomAccessFile randomAccessFile = null;
IInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(rarFile, "r");
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
int[] in = new int[inArchive.getNumberOfItems()];
for (int i = 0; i < in.length; i++) {
in[i] = i;
}
inArchive.extract(in, false, new ExtractCallback(inArchive, outputDir.getAbsolutePath(), extractedFiles));
} finally {
if (randomAccessFile != null) {
randomAccessFile.close();
}
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
e.printStackTrace();
}
}
}
return new ArrayList<>(extractedFiles);
}
private static class ExtractCallback implements IArchiveExtractCallback {
private IInArchive inArchive;
private String outDir;
private Set<File> extractedFiles;
private OutputStream fos = null;
private boolean closeStreamAfterOperation = false;
public ExtractCallback(IInArchive inArchive, String outDir, Set<File> extractedFiles) {
this.inArchive = inArchive;
this.outDir = outDir;
this.extractedFiles = extractedFiles;
}
@Override
public void setCompleted(long arg0) throws SevenZipException {}
@Override
public void setTotal(long arg0) throws SevenZipException {}
@Override
public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {
final String path = (String) inArchive.getProperty(index, PropID.PATH);
return new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
File file = new File(outDir, path);
try {
if (data.length == 0) return 0;
file.getParentFile().mkdirs();
if (fos == null) {
fos = new FileOutputStream(file);
closeStreamAfterOperation = true;
}
fos.write(data);
fos.flush();
extractedFiles.add(file);
} catch (IOException e) {
throw new SevenZipException("Error writing data to file: " + path, e);
}
return data.length;
}
};
}
@Override
public void prepareOperation(ExtractAskMode arg0) throws SevenZipException {}
@Override
public void setOperationResult(ExtractOperationResult extractOperationResult) throws SevenZipException {
if (closeStreamAfterOperation && fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new SevenZipException("Error closing file output stream", e);
} finally {
closeStreamAfterOperation = false;
fos = null;
}
}
}
}
}3. Write a test class to verify the extraction:
package rar5;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RAR5ExtractorTest {
public static void main(String[] args) {
File rarDirFile = new File("src/main/resources/rar5Test06.rarbak");
File outDirFile = new File("src/main/resources/temp/rar5Test06.rar");
Rar5DocExtractor extractor = new Rar5DocExtractor();
try {
List<File> extractedFiles = extractor.extractFiles(rarDirFile, outDirFile);
System.out.println("Extracted files:");
for (File file : extractedFiles) {
System.out.println(file.getAbsolutePath());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
