Skip to content

Instantly share code, notes, and snippets.

@borisbrodski
Last active June 6, 2023 03:29
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save borisbrodski/6120309 to your computer and use it in GitHub Desktop.
Save borisbrodski/6120309 to your computer and use it in GitHub Desktop.
7-Zip-JBinding examples: Snippet to extract all files from an archive into a specified folder on the disk. Usage: java -classpath ... example.ExtractExample [-t] <archive-to-extract> <output-folder> [mask] -t - test files mask - match files to extract, for example, *.txt
package example;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
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 ExtractExample {
static class ExtractionException extends Exception {
private static final long serialVersionUID = -5108931481040742838L;
ExtractionException(String msg) {
super(msg);
}
public ExtractionException(String msg, Exception e) {
super(msg, e);
}
}
class ExtractCallback implements IArchiveExtractCallback {
private ISevenZipInArchive inArchive;
private int index;
private OutputStream outputStream;
private File file;
private ExtractAskMode extractAskMode;
private boolean isFolder;
ExtractCallback(ISevenZipInArchive inArchive) {
this.inArchive = inArchive;
}
@Override
public void setTotal(long total) throws SevenZipException {
}
@Override
public void setCompleted(long completeValue) throws SevenZipException {
}
@Override
public ISequentialOutStream getStream(int index,
ExtractAskMode extractAskMode) throws SevenZipException {
closeOutputStream();
this.index = index;
this.extractAskMode = extractAskMode;
this.isFolder = (Boolean) inArchive.getProperty(index,
PropID.IS_FOLDER);
if (extractAskMode != ExtractAskMode.EXTRACT) {
// Skipped files or files being tested
return null;
}
String path = (String) inArchive.getProperty(index, PropID.PATH);
file = new File(outputDirectoryFile, path);
if (isFolder) {
createDirectory(file);
return null;
}
createDirectory(file.getParentFile());
try {
outputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
throw new SevenZipException("Error opening file: "
+ file.getAbsolutePath(), e);
}
return new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
try {
outputStream.write(data);
} catch (IOException e) {
throw new SevenZipException("Error writing to file: "
+ file.getAbsolutePath());
}
return data.length; // Return amount of consumed data
}
};
}
private void createDirectory(File parentFile) throws SevenZipException {
if (!parentFile.exists()) {
if (!parentFile.mkdirs()) {
throw new SevenZipException("Error creating directory: "
+ parentFile.getAbsolutePath());
}
}
}
private void closeOutputStream() throws SevenZipException {
if (outputStream != null) {
try {
outputStream.close();
outputStream = null;
} catch (IOException e) {
throw new SevenZipException("Error closing file: "
+ file.getAbsolutePath());
}
}
}
@Override
public void prepareOperation(ExtractAskMode extractAskMode)
throws SevenZipException {
}
@Override
public void setOperationResult(
ExtractOperationResult extractOperationResult)
throws SevenZipException {
closeOutputStream();
String path = (String) inArchive.getProperty(index, PropID.PATH);
if (extractOperationResult != ExtractOperationResult.OK) {
throw new SevenZipException("Invalid file: " + path);
}
if (!isFolder) {
switch (extractAskMode) {
case EXTRACT:
System.out.println("Extracted " + path);
break;
case TEST:
System.out.println("Tested " + path);
default:
}
}
}
}
private String archive;
private String outputDirectory;
private File outputDirectoryFile;
private boolean test;
private String filterRegex;
ExtractExample(String archive, String outputDirectory, boolean test, String filter) {
this.archive = archive;
this.outputDirectory = outputDirectory;
this.test = test;
this.filterRegex = filterToRegex(filter);
}
void extract() throws ExtractionException {
checkArchiveFile();
prepareOutputDirectory();
extractArchive();
}
private void prepareOutputDirectory() throws ExtractionException {
outputDirectoryFile = new File(outputDirectory);
if (!outputDirectoryFile.exists()) {
outputDirectoryFile.mkdirs();
} else {
if (outputDirectoryFile.list().length != 0) {
throw new ExtractionException("Output directory not empty: "
+ outputDirectory);
}
}
}
private void checkArchiveFile() throws ExtractionException {
if (!new File(archive).exists()) {
throw new ExtractionException("Archive file not found: " + archive);
}
if (!new File(archive).canRead()) {
System.out.println("Can't read archive file: " + archive);
}
}
public void extractArchive() throws ExtractionException {
RandomAccessFile randomAccessFile;
boolean ok = false;
try {
randomAccessFile = new RandomAccessFile(archive, "r");
} catch (FileNotFoundException e) {
throw new ExtractionException("File not found", e);
}
try {
extractArchive(randomAccessFile);
ok = true;
} finally {
try {
randomAccessFile.close();
} catch (Exception e) {
if (ok) {
throw new ExtractionException("Error closing archive file",
e);
}
}
}
}
private static String filterToRegex(String filter) {
if (filter == null) {
return null;
}
return "\\Q" + filter.replace("*", "\\E.*\\Q") + "\\E";
}
private void extractArchive(RandomAccessFile file)
throws ExtractionException {
ISevenZipInArchive inArchive;
boolean ok = false;
try {
inArchive = SevenZip.openInArchive(null,
new RandomAccessFileInStream(file));
} catch (SevenZipException e) {
throw new ExtractionException("Error opening archive", e);
}
try {
int[] ids = null; // All items
if (filterRegex != null) {
ids = filterIds(inArchive, filterRegex);
}
inArchive.extract(ids, test, new ExtractCallback(inArchive));
ok = true;
} catch (SevenZipException e) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Error extracting archive '");
stringBuilder.append(archive);
stringBuilder.append("': ");
stringBuilder.append(e.getMessage());
if (e.getCause() != null) {
stringBuilder.append(" (");
stringBuilder.append(e.getCause().getMessage());
stringBuilder.append(')');
}
String message = stringBuilder.toString();
throw new ExtractionException(message, e);
} finally {
try {
inArchive.close();
} catch (SevenZipException e) {
if (ok) {
throw new ExtractionException("Error closing archive", e);
}
}
}
}
private static int[] filterIds(ISevenZipInArchive inArchive, String regex) throws SevenZipException {
List<Integer> idList = new ArrayList<Integer>();
int numberOfItems = inArchive.getNumberOfItems();
Pattern pattern = Pattern.compile(regex);
for (int i = 0; i < numberOfItems; i++) {
String path = (String) inArchive.getProperty(i, PropID.PATH);
String fileName = new File(path).getName();
if (pattern.matcher(fileName).matches()) {
idList.add(i);
}
}
int[] result = new int[idList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = idList.get(i);
}
return result ;
}
public static void main(String[] args) {
boolean test = false;
String filter = null;
List<String> argList = new ArrayList<String>(Arrays.asList(args));
if (argList.size() > 0 && argList.get(0).equals("-t")) {
argList.remove(0);
test = true;
}
if (argList.size() != 2 && argList.size() != 3) {
System.out.println("Usage:");
System.out
.println("java -cp ... example.ExtractExample [-t] <archive> <output-dir> [filter]");
System.exit(1);
}
if (argList.size() == 3) {
filter = argList.get(2);
}
try {
new ExtractExample(argList.get(0), argList.get(1), test, filter).extract();
System.out.println("Extraction successfull");
} catch (ExtractionException e) {
System.err.println("ERROR: " + e.getLocalizedMessage());
e.printStackTrace();
}
}
}
@tionu
Copy link

tionu commented Mar 19, 2018

small bug fix: sometimes, paths inside zip files might contain trailing white spaces.
e.g. "sub1\another_subfolder_with_trailing_whitespace \filename.txt"
windows can't handle paths with trailing white spaces und thus you'll get a FileNotFoundException.
suggestion for lines 74/75 to omit trailing whitespaces:

		`String path = (String) inArchive.getProperty(index, PropID.PATH);
		path = path.replaceAll("\\s*\\\\", "\\\\").trim();
		file = new File(outputDirectoryFile, path);`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment