A classe ZipUtils, apresentada a seguir, dispõe de dois métodos públicos estáticos: compress e extract.
Utilidade para ela não falta!
Eu por exemplo já criei programas que geram backups, fiz servlets que compactavam arquivos quando o cliente solicitava download, etc.
Abaixo um simples exemplo de como utilizá-la:
import java.io.*;
import br.com.staroski.tools.zip.*;
public class Exemplo {
public static void main(String[] args) {
try {
// para compactar faça
File origem = new File("caminho completo do arquivo ou diretório a ser compactado");
File destino = new File("caminho completo do arquivo compactado a ser criado");
System.out.println("compactando arquivo...");
ZipUtils.compress(origem, destino);
System.out.println("arquivo compactado com sucesso!");
// para descompactar faça
origem = new File("caminho completo do arquivo a ser descompactado");
destino = new File("caminho do diretório onde o arquivo será descompactado");
System.out.println("descompactando arquivo...");
ZipUtils.extract(origem, destino);
System.out.println("arquivo descompactado com sucesso!");
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Aqui está o fonte da classe, recomendo baixar diretamente pelo GitHub.
package br.com.staroski.tools.zip;
import static br.com.staroski.tools.io.IO.*;
import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
/**
* Classe utilitária para compactação e descompactação de arquivos ZIP
*
* @author Ricardo Artur Staroski
*/
public final class ZipUtils {
/**
* Compacta determindado arquivo ou diretório para o arquivo ZIP
* especificado
*
* @param input
* O arquivo ou diretório de entrada
* @param output
* O arquivo ZIP de saída
*
*@return O checksum da compactação do arquivo
*/
public static long compress(final File input, final File output) throws IOException {
if (!input.exists()) {
throw new IOException(input.getName() + " não existe!");
}
if (output.exists()) {
if (output.isDirectory()) {
throw new IllegalArgumentException("\"" + output.getAbsolutePath() + "\" não é um arquivo!");
}
} else {
final File parent = output.getParentFile();
if (parent != null) {
parent.mkdirs();
}
output.createNewFile();
}
Checksum checksum = createChecksum();
final ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(output));
zip.setLevel(Deflater.BEST_COMPRESSION);
compressInternal(null, input, zip, checksum);
zip.finish();
zip.flush();
zip.close();
return checksum.getValue();
}
/**
* Extrai um arquivo ZIP para o diretório especificado
*
* @param input
* O arquivo ZIP de entrada
* @param output
* O diretório de saída
*@return O checksum da descompactação do arquivo
*/
public static long extract(final File input, final File output) throws IOException {
if (input.exists()) {
if (input.isDirectory()) {
throw new IllegalArgumentException("\"" + input.getAbsolutePath() + "\" não é um arquivo!");
}
} else {
throw new IllegalArgumentException("\"" + input.getAbsolutePath() + "\" não existe!");
}
if (output.exists()) {
if (output.isFile()) {
throw new IllegalArgumentException("\"" + output.getAbsolutePath() + "\" não é um diretório!");
}
}
Checksum checksum = createChecksum();
final ZipInputStream zip = new ZipInputStream(new FileInputStream(input));
extractInternal(zip, output, checksum);
zip.close();
return checksum.getValue();
}
// Adiciona determinado arquivo ao ZIP
private static void compressInternal(final String caminho, final File arquivo, final ZipOutputStream zip, Checksum checksum) throws IOException {
final boolean dir = arquivo.isDirectory();
String nome = arquivo.getName();
nome = (caminho != null ? caminho + "/" + nome : nome);
final ZipEntry item = new ZipEntry(nome + (dir ? "/" : ""));
item.setTime(arquivo.lastModified());
zip.putNextEntry(item);
if (dir) {
zip.closeEntry();
final File[] arquivos = arquivo.listFiles();
for (int i = 0; i < arquivos.length; i++) {
// recursivamente adiciona outro arquivo ao ZIP
compressInternal(nome, arquivos[i], zip, checksum);
}
} else {
item.setSize(arquivo.length());
final FileInputStream entrada = new FileInputStream(arquivo);
copy(entrada, zip, checksum);
entrada.close();
zip.closeEntry();
}
}
private static Checksum createChecksum() {
return new CRC32();
}
// Retira determinado elemento do arquivo ZIP
private static void extractInternal(final ZipInputStream zip, final File pasta, Checksum checksum) throws IOException {
ZipEntry elemento = null;
while ((elemento = zip.getNextEntry()) != null) {
String nome = elemento.getName();
nome = nome.replace('/', File.separatorChar);
nome = nome.replace('\\', File.separatorChar);
File arquivo = new File(pasta, nome);
if (elemento.isDirectory()) {
arquivo.mkdirs();
} else {
boolean existe = arquivo.exists();
if (!existe) {
final File parent = arquivo.getParentFile();
if (parent != null) {
parent.mkdirs();
}
arquivo.createNewFile();
}
boolean oculto = false;
boolean somenteLeitura = false;
if (existe) {
oculto = arquivo.isHidden();
if (oculto) {
Files.setAttribute(arquivo.toPath(), "dos:hidden", false);
}
somenteLeitura = !arquivo.canWrite();
if (somenteLeitura) {
arquivo.setWritable(true);
}
}
OutputStream saida = new FileOutputStream(arquivo);
copy(zip, saida, checksum);
saida.close();
if (existe) {
if (somenteLeitura) {
arquivo.setWritable(false);
}
if (oculto) {
Files.setAttribute(arquivo.toPath(), "dos:hidden", true);
}
}
}
arquivo.setLastModified(elemento.getTime());
}
}
// Construtor privado - Náo há razão em instanciar esta classe
private ZipUtils() {
}
}
Se você não quiser baixar do GitHub, então terá de copiar a classe abaixo também pois a ZipUtils depende dela:
package br.com.staroski.tools.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.*;
/**
* Classe utilitária para operações de I/O
*
* @author Ricardo Artur Staroski
*/
public final class IO {
/**
* Copia o arquivo de origem para o arquivo de destino.
*
* @param from
* O arquivo de origem.
* @param to
* O arquivo de destino.
* @throws IOException
*/
public static void copy(File from, File to) throws IOException {
InputStream in = new FileInputStream(from);
OutputStream out = new FileOutputStream(to);
copy(in, out);
in.close();
out.close();
to.setLastModified(from.lastModified());
}
/**
* Copia o arquivo de origem para o arquivo de destino.
*
* @param from
* O arquivo de origem.
* @param to
* O arquivo de destino.
* @param checksum
* O checksum da escrita.
* @throws IOException
*/
public static void copy(File from, File to, Checksum checksum) throws IOException {
InputStream in = new FileInputStream(from);
OutputStream out = new FileOutputStream(to);
copy(in, out, checksum);
in.close();
out.close();
to.setLastModified(from.lastModified());
}
/**
* Copia o conteúdo do stream de entrada para o stream de saída.
*
* @param from
* O stream de entrada.
* @param to
* O stream de saída.
* @throws IOException
*/
public static void copy(InputStream from, OutputStream to) throws IOException {
final int count = BLOCK_SIZE;
byte[] bytes = new byte[count];
for (int read = -1; (read = from.read(bytes, 0, count)) != -1; to.write(bytes, 0, read))
;
to.flush();
}
/**
* Copia o conteúdo do stream de entrada para o stream de saída.
*
* @param from
* O stream de entrada.
* @param to
* O stream de saída.
* @param checksum
* O checksum da escrita.
* @throws IOException
*/
public static void copy(InputStream from, OutputStream to, Checksum checksum) throws IOException {
final int count = BLOCK_SIZE;
byte[] bytes = new byte[count];
for (int read = -1; (read = from.read(bytes, 0, count)) != -1; to.write(bytes, 0, read)) {
checksum.update(bytes, 0, read);
}
to.flush();
}
/**
* Copia o arquivo de origem para o arquivo de destino.
*
* @param from
* O caminho do arquivo de origem.
* @param to
* O caminho do arquivo de destino.
* @throws IOException
*/
public static void copy(String from, String to) throws IOException {
copy(new FileInputStream(from), new FileOutputStream(to));
}
/**
* Copia o arquivo de origem para o arquivo de destino.
*
* @param from
* O caminho do arquivo de origem.
* @param to
* O caminho do arquivo de destino.
* @param checksum
* O checksum da escrita.
* @throws IOException
*/
public static void copy(String from, String to, Checksum checksum) throws IOException {
copy(new FileInputStream(from), new FileOutputStream(to), checksum);
}
/**
* Analisa o arquivo informado, se o mesmo não existir, um novo é criado
*
* @param file
* O arquivo a ser verificado
* @return O próprio parâmetro
* @throws IOException
*/
public static File createIfNotExists(File file) throws IOException {
if (!file.exists()) {
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
file.createNewFile();
}
return file;
}
/**
* Apaga o arquivo informado
*
* @param file
* O arquivo a ser apagado
* @throws IOException
*/
public static void delete(File file) throws IOException {
Files.deleteIfExists(file.toPath());
}
/**
* Apaga o arquivo informado
*
* @param file
* O arquivo a ser apagado
* @throws IOException
*/
public static void delete(String file) throws IOException {
delete(new File(file));
}
/**
* Obtém todas as linhas do arquivo informado
*
* @param file
* O arquivo do qual se deseja ler as linhas
* @return Uma lista de contendo as linhas do arquivo
* @throws IOException
*/
public static List<String> readLines(File file) throws IOException {
List<String> lines = new ArrayList<String>();
BufferedReader input = new BufferedReader(new FileReader(file));
String line = null;
while ((line = input.readLine()) != null) {
lines.add(line);
}
input.close();
return lines;
}
/**
* Grava as linhas no arquivo informado
*
* @param lines
* As linhas a serem gravadas
* @param file
* O arquivo no qual se deseja gravar as linhas
* @throws IOException
*/
public static void writeLines(File file, List<String> lines) throws IOException {
BufferedWriter output = new BufferedWriter(new FileWriter(file));
for (int i = 0, n = lines.size(); i < n; i++) {
if (i > 0) {
output.newLine();
}
output.write(lines.get(i));
}
output.flush();
output.close();
}
/**
* Tamanho padrão, 8KB, utilizado para blocos de memória.
*/
public static int BLOCK_SIZE = 8192;
// não faz sentido instanciar esta classe
private IO() {
}
}