/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.utilities;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Zip and GZip utilities.
*
* @author Edwin Shin
*/
public class Zip {
private static final int BUFFER = 2048;
/**
* Create a zip file.
*
* @param destination
* The zip file to create.
* @param source
* The file or directory to be zipped.
* @throws FileNotFoundException
* @throws IOException
*/
public static void zip(File destination, File source)
throws FileNotFoundException, IOException {
zip(destination, new File[] {source});
}
/**
* Create a zip file.
*
* @param destination
* The zip file to create.
* @param source
* The File array to be zipped.
* @throws FileNotFoundException
* @throws IOException
*/
public static void zip(File destination, File[] source)
throws FileNotFoundException, IOException {
FileOutputStream dest = new FileOutputStream(destination);
ZipOutputStream zout =
new ZipOutputStream(new BufferedOutputStream(dest));
for (File element : source) {
zip(null, element, zout);
}
zout.close();
}
/**
* Extracts the file given by entryName to destination.
*
* @param zipFile
* @param entryName
* @param destination
* The extracted destination File.
* @throws IOException
*/
public static void extractFile(File zipFile,
String entryName,
File destination) throws IOException {
ZipFile zip = new ZipFile(zipFile);
try {
ZipEntry entry = zip.getEntry(entryName);
if (entry != null) {
// Get an input stream for the entry.
InputStream entryStream = zip.getInputStream(entry);
try {
// Create the output file
File parent = destination.getParentFile();
if (parent != null) {
parent.mkdirs();
}
FileOutputStream file = new FileOutputStream(destination);
try {
// Allocate a buffer for reading the entry data.
byte[] data = new byte[BUFFER];
int bytesRead;
// Read the entry data and write it to the output file.
while ((bytesRead = entryStream.read(data)) != -1) {
file.write(data, 0, bytesRead);
}
} finally {
file.close();
}
} finally {
entryStream.close();
}
} else {
throw new IOException(zipFile.getName() + " does not contain: "
+ entryName);
}
} finally {
zip.close();
}
}
/**
* Unzips the InputStream to the given destination directory.
*
* @param is
* @param destDir
* @throws FileNotFoundException
* @throws IOException
*/
public static void unzip(InputStream is, File destDir)
throws FileNotFoundException, IOException {
BufferedOutputStream dest = null;
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
//System.out.println("Extracting: " + entry);
if (entry.isDirectory()) {
// Otherwise, empty directories do not get created
(new File(destDir, entry.getName())).mkdirs();
} else {
File f = new File(destDir, entry.getName());
f.getParentFile().mkdirs();
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new FileOutputStream(f);
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
}
zis.close();
}
public static void gzip() {
// TODO
}
public static void gunzip() {
// TODO
}
// Convenience methods
public static void zip(String destination, String source)
throws FileNotFoundException, IOException {
zip(new File(destination), new File(source));
}
public static void unzip(InputStream is, String destDir)
throws FileNotFoundException, IOException {
unzip(is, new File(destDir));
}
public static void main(String[] args) {
// 2 arguments: zipfile, source/destination
// whether or not the zipfile exists, i.e.:
// if zipfile exists
// if zipfile extension == zip, then unzip
// if zipfile extension == gz, then gunzip
// else
// if zipfile extension == zip, then zip
// if zipfile extension == gz, then gzip
// valid actions are: zip, unzip, gzip, and gunzip
// should consider making source/destination optional (i.e., assume current directory)
// might consider taking a filefilter
}
private static void zip(String baseDir, File source, ZipOutputStream zout)
throws IOException {
ZipEntry entry = null;
if (baseDir == null || baseDir.equals(".") || baseDir.equals("./")) {
baseDir = "";
}
if (source.isDirectory()) {
// If there's a "better" way to indicate a directory, go ahead :)
// Perhaps at least use File.separator and not "/"
entry = new ZipEntry(baseDir + source.getName() + "/");
} else {
entry = new ZipEntry(baseDir + source.getName());
}
zout.putNextEntry(entry);
//System.out.println("Adding " + entry.getName());
if (!source.isDirectory()) {
byte data[] = new byte[BUFFER];
FileInputStream fis = new FileInputStream(source);
BufferedInputStream origin = new BufferedInputStream(fis, BUFFER);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
zout.write(data, 0, count);
}
fis.close();
origin.close();
} else {
File files[] = source.listFiles();
for (File element : files) {
zip(entry.getName(), element, zout);
}
}
}
}