sábado, 5 de fevereiro de 2011

Descompactador de Arquivos


Há alguns dias eu havia mostrado como criar um compactador de arquivos, agora vou demonstrar como criar um descompactador de arquivos, para trabalhar em conjunto com o compactador.
Falando à nível de código, é praticamente a mesma coisa, apenas precisamos inverter os objetos.
Para relembrar, segue o código do compactador, a explicação do código está aqui.
public static void compactar(String arquivoOrigem, String arquivoZipado) {
byte[] buf new byte[1024];
try {
ZipOutputStream out 
new ZipOutputStream(new FileOutputStream(arquivoZipado));
FileInputStream in new FileInputStream(arquivoOrigem);
out.putNextEntry(new ZipEntry(arquivoOrigem));
int len;
while((len in.read(buf)) > 0) {
out.write(buf0len);
}
out.closeEntry();
in.close();
out.close();
catch (Exception e) {
System.out.println(“deu erro”);
}
}
Esse método cria um objeto ZipOutPutStream para representar o arquivo compactado e um arquivoFileInputStream para representar o arquivo de origem, que será lido.
Para descompactar um arquivo precisamos basicamente inverter esses dois objetos, e suas referências no resto do código, ficando um objeto ZipInputStream para ler o arquivo compactado e um objeto FileOutputStream paracriar um novo arquivo.
Simples né?
Outro esquema interessante, no compactador adicionamos uma nova entrada ao arquivo compactado, utilizando o código putNextEntry, mas no descompactador devemos capturar uma entrada existente, com o códigogetNextEntry.
Para sabermos o nome do arquivo que está dentro da compactação, para poder criá-lo, basta utilizar adicionar ao getNextEntry um getName, ficando objeto.getNextEntry().getName().
Uma observação importante, se você informar apenas o nome para criação do arquivo ele será criado dentro de um buraco negro, ou no melhor dos casos, na pasta do projeto, então você deve obrigatoriamente informar caminho + nome. Para descobrir o caminho onde o arquivo deve ser criado, eu simplesmente pego todos os caracteres do arquivo de origem (c:\pasta\pasta\arquivo.zip) até o ultimo separador de diretório, nesse caso o caractere barra (\).
Está dificil de entender?
Então vamos ver na prática, como estou presumindo que você já fez o compactador e a lógica dele está toda comentada, então só adicionei comentários nos códigos novos/trocados.
public static void descompactar(String arquivoZipado) {
byte[] buf = new byte[1024];
//verifica o local onde o arquivo compactado está, para salvar
//o arquivo que será criado pega todos os caracteres da string
//até a última barra, ou seja, a string do arquivoZipado está
//”c:\pasta\pasta\pasta\arquivo.zip” e a variável pathArquivo
//ficará c:\pasta\pasta\pasta
String pathArquivo = arquivoZipado.substring(
0, arquivoZipado.lastIndexOf(“\\”));
try {
//O arquivo de escrita ZipOutputStream foi trocado por um
//arquivo de leitura (queremos ler o zip)
ZipInputStream in = new ZipInputStream(new FileInputStream(arquivoZipado));
//O arquivo de leitura FileInputStream foi trocado por um
//arquivo de escrita (queremos criar um arquivo)
//O arquivo será criado no mesmo diretório do arquivo compactado
FileOutputStream out = new FileOutputStream(
pathArquivo + “\\” + in.getNextEntry().getName());
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.closeEntry();
out.close();
in.close();
catch (Exception e) {
System.out.println(“deu erro”);
}
}
É possível compactar/descompactar arquivos compactados com qualquer extensão (você pode criar a sua extensão), desde que o arquivo esteja compactado a extensão não importa, também é possível descompactar um arquivo que foi compactado pelo winrar ou winzip, só testei com esses dois mas deve funcionar com outros também.
Esses dois códigos de exemplo só compactam/descompactam um único arquivo, mas não fique desanimado, é possível aprimorar o código.
Uma dica é criar um loop de controle e, para compactar, repete todo o código desde FileInputStream eputNextEntry (que adiciona um novo arquivo ao zip) até o final do while. Para descompactar em massa, crie um loop para controlar desde o FileOutputStream getNextEntry (que captura o próximo arquivo que está dentro do zip) até o final do while. Importante, para o descompactador verifica se existe uma próxima entrada adicionando um tratamento de erro para finalizar a descompactação caso não exista mais arquivos dentro do zip.
Qualquer dúvida, comentários abaixo!
Enjoy.

Nenhum comentário:

Postar um comentário