Code snippets
Index
Here you can find many code snippets, example of how to
perform basic operations with 7-Zip-JBinding. All examples are part of the JUnit tests.
Each example runs on one of the test archives. JUnit tests check, that the output of the
snippet is exactly the one published on this page. Below is a list of the test archives
for this page. You can download all test archives in as a
single ZIP file.
- simple.zip
$ 7z l simple.zip
7-Zip 4.65 Copyright (c) 1999-2009 Igor Pavlov 2009-02-03
p7zip Version 4.65 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)
Listing archive: simple.zip
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2009-08-04 11:26:16 ..... 4481 68 file1.txt
2009-08-04 11:27:34 ..... 75 62 file2.txt
2009-08-04 13:53:06 D.... 0 0 folder
2009-08-04 13:53:40 ..... 6 6 folder/file in folder.txt
------------------- ----- ------------ ------------ ------------------------
4562 136 3 files, 1 folders
-
multipart-7z.7z.001;
multipart-7z.7z.002;
multipart-7z.7z.003;
multipart-7z.7z.004
$ 7z l multipart-7z.7z.001
7-Zip 4.65 Copyright (c) 1999-2009 Igor Pavlov 2009-02-03
p7zip Version 4.65 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)
Listing archive: multipart-7z.7z.001
Method = LZMA
Solid = +
Blocks = 1
Physical Size = 331
Headers Size = 217
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2009-08-04 13:53:39 ....A 6 114 folder/file in folder.txt
2009-08-04 11:26:16 ....A 4481 file1.txt
2009-08-04 11:27:33 ....A 75 file2.txt
2009-08-04 13:53:05 D.... 0 0 folder
------------------- ----- ------------ ------------ ------------------------
4562 114 3 files, 1 folders
-
multipart-rar.part1.rar;
multipart-rar.part2.rar;
multipart-rar.part3.rar;
multipart-rar.part4.rar;
multipart-rar.part5.rar
$ 7z l multipart-rar.part1.rar
7-Zip 4.65 Copyright (c) 1999-2009 Igor Pavlov 2009-02-03
p7zip Version 4.65 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)
Listing archive: multipart-rar.part1.rar
Solid = -
Blocks = 4
Multivolume = +
Volumes = 5
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2009-08-04 13:53:39 ..... 6 6 folder/file in folder.txt
2009-08-04 11:26:16 ..... 4481 4481 file1.txt
2009-08-04 11:27:33 ..... 75 75 file2.txt
2009-08-04 13:53:05 D.... 0 0 folder
------------------- ----- ------------ ------------ ------------------------
4562 4562 3 files, 1 folders
The 7-Zip-JBinding library offers two different interfaces:
standard and simple. The standard interface directly maps all native
7-Zip library methods providing C++ like interface. The simple interface
is a try to provide more Java-like easy to use interface. It was
designed either for quick coding and easy start and not for feature
richness nor for performance.
The following examples will be presented in both standard and
simple interface beginning with as simple interface. Please note, that
the full performance can only be reached with the standard interface.
This example shows how to print a list of items of archive using
simple interface.
import java.io.IOException;
import java.io.RandomAccessFile;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
public class ListItemsSimple {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java ListItemsSimple <archive-name>");
return;
}
RandomAccessFile randomAccessFile = null;
ISevenZipInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(args[0], "r");
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(randomAccessFile));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
System.out.println(" Size | Compr.Sz. | Filename");
System.out.println("----------+-----------+---------");
for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
System.out.println(String.format("%9s | %9s | %s",
item.getSize(),
item.getPackedSize(),
item.getPath()));
}
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
The output for the test archive:
Size | Compr.Sz. | Filename
----------+-----------+---------
4481 | 68 | file1.txt
75 | 62 | file2.txt
0 | 0 | folder
6 | 6 | folder/file in folder.txt
Please note, that not all archive formats support the "folder"
items, like "folder/" in our example. Also please note, that packed size
in this example as almost all other properties can return null. A
returned null value means, that either the property is not supported by
the particular archive format or not known for the particular item.
This example shows how to print a list of items of archive using
standard interface.
import java.io.IOException;
import java.io.RandomAccessFile;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
public class ListItemsStandard {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java ListItemsStandard <archive-name>");
return;
}
RandomAccessFile randomAccessFile = null;
ISevenZipInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(args[0], "r");
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(randomAccessFile));
System.out.println(" Size | Compr.Sz. | Filename");
System.out.println("----------+-----------+---------");
int itemCount = inArchive.getNumberOfItems();
for (int i = 0; i < itemCount; i++) {
System.out.println(String.format("%9s | %9s | %s",
inArchive.getProperty(i, PropID.SIZE),
inArchive.getProperty(i, PropID.PACKED_SIZE),
inArchive.getProperty(i, PropID.PATH)));
}
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
The output for the test archive is the same:
Size | Compr.Sz. | Filename
----------+-----------+---------
4481 | 68 | file1.txt
75 | 62 | file2.txt
0 | 0 | folder
6 | 6 | folder/file in folder.txt
This section will show how to access the compressed data of the
archive items. The following examples will calculate a simple checksum
of each archive item.
This example shows how to get content of the items of the archive
using simple interface. In order to consume extracted content the simple
checksum will be calculated.
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
public class ExtractItemsSimple {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java ExtractItemsSimple <archive-name>");
return;
}
RandomAccessFile randomAccessFile = null;
ISevenZipInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(args[0], "r");
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(randomAccessFile));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
System.out.println(" Hash | Size | Filename");
System.out.println("----------+------------+---------");
for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
final int[] hash = new int[] { 0 };
if (!item.isFolder()) {
ExtractOperationResult result;
final long[] sizeArray = new long[1];
result = item.extractSlow(new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
hash[0] ^= Arrays.hashCode(data);
sizeArray[0] += data.length;
return data.length;
}
});
if (result == ExtractOperationResult.OK) {
System.out.println(String.format("%9X | %10s | %s",
hash[0], sizeArray[0], item.getPath()));
} else {
System.err.println("Error extracting item: " + result);
}
}
}
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
Here is the output of the last snippet:
Hash | Size | Filename
----------+------------+---------
C1FD1029 | 4481 | file1.txt
8CB12E6A | 75 | file2.txt
E8EEC7F4 | 6 | folder/file in folder.txt
The following two examples show how to perform the same
extracting task using standard interface. As in the previous example,
the simple checksum will be calculated in order to consume the extracted
data.
First example traverse the entire archive and uses call back
method to choose on the fly whether proceed with the extraction of an
item or not. The second example prepare a list of items for extraction.
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import net.sf.sevenzipjbinding.ExtractAskMode;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IArchiveExtractCallback;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
public class ExtractItemsStandardCallback {
public static class MyExtractCallback implements IArchiveExtractCallback {
private int hash = 0;
private int size = 0;
private int index;
private boolean skipExtraction;
private ISevenZipInArchive inArchive;
public MyExtractCallback(ISevenZipInArchive inArchive) {
this.inArchive = inArchive;
}
public ISequentialOutStream getStream(int index,
ExtractAskMode extractAskMode) throws SevenZipException {
this.index = index;
skipExtraction = (Boolean) inArchive
.getProperty(index, PropID.IS_FOLDER);
if (skipExtraction || extractAskMode != ExtractAskMode.EXTRACT) {
return null;
}
return new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
hash ^= Arrays.hashCode(data);
size += data.length;
return data.length;
}
};
}
public void prepareOperation(ExtractAskMode extractAskMode)
throws SevenZipException {
}
public void setOperationResult(ExtractOperationResult
extractOperationResult) throws SevenZipException {
if (skipExtraction) {
return;
}
if (extractOperationResult != ExtractOperationResult.OK) {
System.err.println("Extraction error");
} else {
System.out.println(String.format("%9X | %10s | %s", hash, size,
inArchive.getProperty(index, PropID.PATH)));
hash = 0;
size = 0;
}
}
public void setCompleted(long completeValue) throws SevenZipException {
}
public void setTotal(long total) throws SevenZipException {
}
}
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java ExtractItemsStandard <arch-name>");
return;
}
RandomAccessFile randomAccessFile = null;
ISevenZipInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(args[0], "r");
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(randomAccessFile));
System.out.println(" Hash | Size | Filename");
System.out.println("----------+------------+---------");
int[] in = new int[inArchive.getNumberOfItems()];
for (int i = 0; i < in.length; i++) {
in[i] = i;
}
inArchive.extract(in, false,
new MyExtractCallback(inArchive));
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.sevenzipjbinding.ExtractAskMode;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IArchiveExtractCallback;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
public class ExtractItemsStandard {
public static class MyExtractCallback implements IArchiveExtractCallback {
private int hash = 0;
private int size = 0;
private int index;
private ISevenZipInArchive inArchive;
public MyExtractCallback(ISevenZipInArchive inArchive) {
this.inArchive = inArchive;
}
public ISequentialOutStream getStream(int index,
ExtractAskMode extractAskMode) throws SevenZipException {
this.index = index;
if (extractAskMode != ExtractAskMode.EXTRACT) {
return null;
}
return new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
hash ^= Arrays.hashCode(data);
size += data.length;
return data.length;
}
};
}
public void prepareOperation(ExtractAskMode extractAskMode)
throws SevenZipException {
}
public void setOperationResult(ExtractOperationResult
extractOperationResult) throws SevenZipException {
if (extractOperationResult != ExtractOperationResult.OK) {
System.err.println("Extraction error");
} else {
System.out.println(String.format("%9X | %10s | %s", hash, size,
inArchive.getProperty(index, PropID.PATH)));
hash = 0;
size = 0;
}
}
public void setCompleted(long completeValue) throws SevenZipException {
}
public void setTotal(long total) throws SevenZipException {
}
}
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java ExtractItemsStandard <arch-name>");
return;
}
RandomAccessFile randomAccessFile = null;
ISevenZipInArchive inArchive = null;
try {
randomAccessFile = new RandomAccessFile(args[0], "r");
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(randomAccessFile));
System.out.println(" Hash | Size | Filename");
System.out.println("----------+------------+---------");
int count = inArchive.getNumberOfItems();
List<Integer> itemsToExtract = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
if (!((Boolean) inArchive.getProperty(i, PropID.IS_FOLDER))
.booleanValue()) {
itemsToExtract.add(Integer.valueOf(i));
}
}
int[] items = new int[itemsToExtract.size()];
int i = 0;
for (Integer integer : itemsToExtract) {
items[i++] = integer.intValue();
}
inArchive.extract(items, false,
new MyExtractCallback(inArchive));
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
Dealing with a multi-part archives is not so easy, as dealing
with a ordinary single part archives. Different archive formats need
different approaches and therefore will be discussed separately.
Multi-part 7z archives are build by simple splitting of solid 7z
archives into multiple peaces. This means, you can easy convert a
multi-part 7z archive into single part 7z archive by concatenation of
all archive parts into a one single file. Here is an example, how you
can do this in a sh-shell.
$ ###
$ ###
$ ###
$ ###
$ 7z a test.7z -v10k somedir/
...
$ ls -l
total 32
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.001
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.002
-rw-r--r-- 1 boris boris 6684 2009-11-29 01:17 test.7z.003
$ ###
$ ###
$ ###
$ cat test.7z.* > test.7z
$ ls -l
total 60
-rw-r--r-- 1 boris boris 27164 2009-11-29 01:18 test.7z
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.001
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.002
-rw-r--r-- 1 boris boris 6684 2009-11-29 01:17 test.7z.003
$ ###
$ ###
$ ###
$ 7z t test.7z
...
Everything is Ok
...
###
###
###
###
$ split -b 15000 -a 3 -d test.7z test2.7z.
$ mv test2.7z.001 test2.7z.002
$ mv test2.7z.000 test2.7z.001
$ ls -l
total 88
-rw-r--r-- 1 boris boris 15000 2009-11-29 01:36 test2.7z.001
-rw-r--r-- 1 boris boris 12164 2009-11-29 01:36 test2.7z.002
-rw-r--r-- 1 boris boris 27164 2009-11-29 01:22 test.7z
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.001
-rw-r--r-- 1 boris boris 10240 2009-11-29 01:17 test.7z.002
-rw-r--r-- 1 boris boris 6684 2009-11-29 01:17 test.7z.003
$ ###
$ ###
$ ###
$ 7z t test2.7z.001
...
Everything is Ok
...
The naming conventions for the volumes of a multi-part 7z archive
are:
- Every file name of a volume should ends with ".7z.XXX", where
X is a digit between 0 and 9. The XXX is a decimal sequential number of
the volume starting with 1. Ending ".7z.000" is not allowed.
It's important to provide corrent names in
IArchiveOpenVolumeCallback.getProperty() method and to
VolumedArchiveInStream class. Also you will probably need to parse
filenames passed to IArchiveOpenVolumeCallback.getStream(String
filename) in order to get a number of the required volume.
Here is an example of how to open a multi-part archive directly
from the file system. In this example all the volumes are named
correctly, so it's no need to parse requred volume name to extract the
index. The volumes already exists under the passed names und can be
directly opened.
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import net.sf.sevenzipjbinding.ArchiveFormat;
import net.sf.sevenzipjbinding.IArchiveOpenVolumeCallback;
import net.sf.sevenzipjbinding.IInStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.impl.VolumedArchiveInStream;
public class OpenMultipartArchive7z {
/**
* In this example we use VolumedArchiveInStream class only.
* It means, we doesn't pass instances of this class directly
* to 7-Zip, so not complete implementation
* of {@link IArchiveOpenVolumeCallback} is required.
* See VolumedArchiveInStream JavaDoc for more information
*/
private static class ArchiveOpenVolumeCallback
implements IArchiveOpenVolumeCallback {
/**
* Cache for opened file streams
*/
private Map<String, RandomAccessFile> openedRandomAccessFileList =
new HashMap<String, RandomAccessFile>();
/**
* This method doesn't needed, if using with VolumedArchiveInStream
* and pass the name of the first archive in constructor.
* (Use two argument constructor)
*
* @see IArchiveOpenVolumeCallback#getProperty(PropID)
*/
public Object getProperty(PropID propID) throws SevenZipException {
return null;
}
/**
*
* The name of the required volume will be calculated out of the
* name of the first volume and volume index. If you need
* need volume index (integer) you will have to parse filename
* and extract index.
*
* <pre>
* int index = filename.substring(filename.length() - 3,
* filename.length());
* </pre>
*
*/
public IInStream getStream(String filename) throws SevenZipException {
try {
RandomAccessFile randomAccessFile = openedRandomAccessFileList
.get(filename);
if (randomAccessFile != null) {
randomAccessFile.seek(0);
return new RandomAccessFileInStream(randomAccessFile);
}
randomAccessFile = new RandomAccessFile(filename, "r");
openedRandomAccessFileList.put(filename, randomAccessFile);
return new RandomAccessFileInStream(randomAccessFile);
} catch (FileNotFoundException fileNotFoundException) {
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Close all opened streams
*/
void close() throws IOException {
for (RandomAccessFile file : openedRandomAccessFileList.values()) {
file.close();
}
}
}
public static void main(String[] args) {
if (args.length == 0) {
System.out.println(
"Usage: java OpenMultipartArchive7z <first-volume>");
return;
}
ArchiveOpenVolumeCallback archiveOpenVolumeCallback = null;
ISevenZipInArchive inArchive = null;
try {
archiveOpenVolumeCallback = new ArchiveOpenVolumeCallback();
inArchive = SevenZip.openInArchive(ArchiveFormat.SEVEN_ZIP,
new VolumedArchiveInStream(args[0],
archiveOpenVolumeCallback));
System.out.println(" Size | Compr.Sz. | Filename");
System.out.println("----------+-----------+---------");
int itemCount = inArchive.getNumberOfItems();
for (int i = 0; i < itemCount; i++) {
System.out.println(String.format("%9s | %9s | %s",
inArchive.getProperty(i, PropID.SIZE),
inArchive.getProperty(i, PropID.PACKED_SIZE),
inArchive.getProperty(i, PropID.PATH)));
}
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (archiveOpenVolumeCallback != null) {
try {
archiveOpenVolumeCallback.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
Here is the output of the last snippet:
Size | Compr.Sz. | Filename
----------+-----------+---------
6 | 114 | folder/file in folder.txt
4481 | null | file1.txt
75 | null | file2.txt
0 | 0 | folder
Since RAR uses its own proprietary format for splitting archives into
multiple volumes, there is no need to use VolumedArchiveInStream in
order to open multi-part RAR archives. To provide access to the different
volumes of a RAR archive, the archive open callback class should
additionally implement the IArchiveOpenVolumeCallback interface.
Here is an example:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import net.sf.sevenzipjbinding.ArchiveFormat;
import net.sf.sevenzipjbinding.IArchiveOpenCallback;
import net.sf.sevenzipjbinding.IArchiveOpenVolumeCallback;
import net.sf.sevenzipjbinding.IInStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
public class OpenMultipartArchiveRar {
private static class ArchiveOpenVolumeCallback
implements IArchiveOpenVolumeCallback, IArchiveOpenCallback {
/**
* Cache for opened file streams
*/
private Map<String, RandomAccessFile> openedRandomAccessFileList =
new HashMap<String, RandomAccessFile>();
/**
* Name of the last volume returned by {@link #getStream(String)}
*/
private String name ;
/**
* This method should at least provide the name of the last
* opened volume (propID=PropID.NAME).
*
* @see IArchiveOpenVolumeCallback#getProperty(PropID)
*/
public Object getProperty(PropID propID) throws SevenZipException {
switch (propID) {
case NAME:
return name ;
}
return null;
}
/**
* The name of the required volume will be calculated out of the
* name of the first volume and a volume index. In case of RAR file,
* the substring ".partNN." in the name of the volume file will
* indicate a volume with id NN. For example:
* <ul>
* <li>test.rar - single part archive or multi-part archive with
* a single volume</li>
* <li>test.part23.rar - 23-th part of a multi-part archive</li>
* <li>test.part001.rar - first part of a multi-part archive.
* "00" indicates, that at least 100 volumes must exist.</li>
* </ul>
*/
public IInStream getStream(String filename) throws SevenZipException {
try {
RandomAccessFile randomAccessFile = openedRandomAccessFileList
.get(filename);
if (randomAccessFile != null) {
randomAccessFile.seek(0);
name = filename;
return new RandomAccessFileInStream(randomAccessFile);
}
randomAccessFile = new RandomAccessFile(filename, "r");
openedRandomAccessFileList.put(filename, randomAccessFile);
name = filename;
return new RandomAccessFileInStream(randomAccessFile);
} catch (FileNotFoundException fileNotFoundException) {
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Close all opened streams
*/
void close() throws IOException {
for (RandomAccessFile file : openedRandomAccessFileList.values()) {
file.close();
}
}
public void setCompleted(Long files, Long bytes) throws SevenZipException {
}
public void setTotal(Long files, Long bytes) throws SevenZipException {
}
}
public static void main(String[] args) {
if (args.length == 0) {
System.out.println(
"Usage: java OpenMultipartArchiveRar <first-volume>");
return;
}
ArchiveOpenVolumeCallback archiveOpenVolumeCallback = null;
ISevenZipInArchive inArchive = null;
try {
archiveOpenVolumeCallback = new ArchiveOpenVolumeCallback();
IInStream inStream = archiveOpenVolumeCallback.getStream(args[0]);
inArchive = SevenZip.openInArchive(ArchiveFormat.RAR, inStream,
archiveOpenVolumeCallback);
System.out.println(" Size | Compr.Sz. | Filename");
System.out.println("----------+-----------+---------");
int itemCount = inArchive.getNumberOfItems();
for (int i = 0; i < itemCount; i++) {
System.out.println(String.format("%9s | %9s | %s",
inArchive.getProperty(i, PropID.SIZE),
inArchive.getProperty(i, PropID.PACKED_SIZE),
inArchive.getProperty(i, PropID.PATH)));
}
} catch (Exception e) {
System.err.println("Error occurs: " + e);
System.exit(1);
} finally {
if (inArchive != null) {
try {
inArchive.close();
} catch (SevenZipException e) {
System.err.println("Error closing archive: " + e);
}
}
if (archiveOpenVolumeCallback != null) {
try {
archiveOpenVolumeCallback.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e);
}
}
}
}
}
Here is the output of the last snippet:
Size | Compr.Sz. | Filename
----------+-----------+---------
6 | 6 | folder/file in folder.txt
4481 | 4481 | file1.txt
75 | 75 | file2.txt
0 | 0 | folder
|