Cree un archivo ZIP
4. Obtenga el flujo de una entrada al llamar a getInputStream( ) en la entrada actual 5 Obtenga el nombre de la entrada al llamar a getName( ) y úsela como nombre del flujo de
salida que recibirá el archivo descomprimido.
6. Para descomprimir la entrada, copie bytes del flujo de entrada al de salida. La descompresión es automática.
7. Por lo general, querrá reportar el progreso de la descompresión, incluido el tamaño de los archivos comprimido y expandido. Para hacer esto puede usar métodos proporcionados por ZipEntry. Para obtener el tamaño descomprimido de un archivo llame a getSize( ). Para obtener el tamaño comprimido, llame a getCompressedSize( ).
8. Cierre los flujos de entrada y de salida.
9. Repita del paso 4 al 7, hasta que se hayan descomprimido todas las entradas. 10. Cierre la instancia de ZipFile.
Análisis
La manera más fácil de descomprimir un archivo ZIP consiste en usar ZipFile, porque afi na el proceso de encontrar y leer cada entrada del archivo. Proporciona tres constructores. El usado aquí es:
ZipFile(String nombreArchivoZip) throws IOException
El nombre del archivo ZIP que se descomprimirá se especifi ca con nombreArchivoZip. Se lanza una IOException si ocurre un error de E/S. Se lanza una ZipException si se especifi ca un archivo ZIP que no es válido. ZipException es una subclase de IOException. Por tanto, al capturar una IOException se manejarán ambas excepciones. Sin embargo, para un manejo de errores más preciso, es necesario manejar ambas excepciones individualmente.
Puede obtenerse una enumeración de las entradas en el archivo ZIP al llamar a entries( ) en la instancia de ZipFile. Aquí se muestra:
Enumeration<? Extends ZipEntry> entries( )
Empleando la enumeración devuelta por entries( ) puede recorrer en ciclo las entradas del archivo, descomprimiendo cada una por turnos. (También omite una entrada, si lo desea. No hay una regla que diga que debe descomprimir todas las entradas de un archivo ZIP).
Para obtener un flujo de entrada, llame a getInputStream( ) en la instancia de ZipFile. Aquí se muestra:
InputStream getInputStream(ZipEntry ze) throws IOException
El fl ujo leerá de la entrada pasada en ze. Se lanza una IOException si ocurre un error de E/S. Se lanza una ZipException si la entrada está en un formato inadecuado.
Puede obtener el nombre de la entrada al llamar a getName( ) en la instancia de ZipEntry. Aquí se muestra:
String getName( )
Puede usar entonces el nombre de la entrada como nombre del archivo de salida restaurado (es decir, descomprimido).
Una vez que haya descomprimido todas las entradas del archivo, debe cerrar la instancia de ZipFile al llamar a close( ), como se muestra aquí:
void close( ) throws IOException
Además de cerrar el archivo ZIP, también cerrará cualquier fl ujo abierto por llamadas a getInputStream( ). (Sin embargo, prefi ero no depender de esto. En cambio, prefi ero cerrar cada fl ujo de entrada por separado, a medida que avanza la descompresión, para no tener varios fl ujos abiertos, pero sin usar, con recursos asignados).
Los tamaños de las entradas comprimida y descomprimida pueden obtenerse al llamar a getCompressedSize( ) y getSize( ), respectivamente. Estos métodos se describieron en la solución anterior. Puede usar esta información para proporcionar retroalimentación acerca del progreso de la descompresión.
Ejemplo
En el siguiente ejemplo se descomprime un archivo ZIP. Reconocerá un nombre de ruta completo para la entrada, pero no creará la ruta del directorio, si no existe. Se trata de una capacidad que puede agregar, si lo desea.
// Descomprime un archivo ZIP. //
// Para usar este programa, especifique el nombre
// del archivo comprimido. Por ejemplo, para descomprimir // un archivo llamado ejemplo.zip use la siguiente
// línea de comandos: //
// java Unzip ejemplo.zip //
// Nota: este programa descomprimirá una entrada // que incluye información de ruta de directorios, // pero no creará la ruta del directorio, si // aún no existe. // import java.io.*; import java.util.zip.*; import java.util.*; class Unzip {
public static void main(String args[ ]) {
BufferedInputStream fin; BufferedOutputStream fout; ZipFile zf;
// Primero se asegura de que se ha especificado un // archivo de entrada.
if(args.length != 1) {
System.out.println("Uso: Unzip nombre"); return;
// Abre el archivo zip. try {
zf = new ZipFile(args[0]); } catch(ZipException exc) {
System.out.println("Archivo ZIP no v\u00a0lido"); return;
} catch(IOException exc) {
System.out.println("Error al abrir el archivo ZIP"); return;
}
// Obtiene una enumeración de las entradas en el archivo. Enumeration<? extends ZipEntry> archivos = zf.entries( ); // Descomprime cada entrada.
while(archivos.hasMoreElements( )) { ZipEntry ze = archivos.nextElement( );
System.out.println("Descomprimiendo " + ze.getName( )); System.out.println(" Tama\u00a4o comprimido: " + ze.getCompressedSize( ) + " Tama\u00a4o expandido: " + ze.getSize( ) + "\n");
// Abre el flujo en la entrada especificada. try {
fin = new BufferedInputStream(zf.getInputStream(ze)); } catch(ZipException exc) {
System.out.println("Archivo ZIP no v\u00a0lido"); break;
} catch(IOException exc) {
System.out.println("Error al abrir la entrada"); break;
}
// Abre el archivo de salida. Usa el nombre proporcionado // por la entrada.
try {
fout = new BufferedOutputStream(
new FileOutputStream(ze.getName( ))); } catch(FileNotFoundException exc) {
System.out.println("No se puede crear el archivo de salida"); // Cierra el flujo de entrada abierto.
try {
fin.close( );
} catch(IOException exc2) {
System.out.println("Error al cerrar el archivo ZIP de entrada"); }
break; }
// Descomprime la entrada. try { int i; do { i = fin.read( ); if(i != –1) fout.write(i); } while(i != –1); } catch(IOException exc) {
System.out.println("Error de archivo mientras se descomprime"); }
// Cierra el archivo de salida para la entrada actual. try {
fout.close( );
} catch(IOException exc) {
System.out.println("Error al cerrar el archivo de salida"); }
// Cierra el flujo para la entrada actual. try {
fin.close( );
} catch(IOException exc) {
System.out.println("Error al cerrar la entrada"); }
}
// Cierra el archivo Zip. try {
zf.close( );
} catch(IOException exc) {
System.out.println("Error al cerrar el archivo Zip"); }
} }
Aquí se muestra la salida de ejemplo: Descomprimiendo VolcarHex.java
Tamaño comprimido: 612 Tamaño expandido: 1384 Descomprimiendo EscribirBytes.java
Tamaño comprimido: 428 Tamaño expandido: 895
Opciones
ZipFile proporciona dos constructores adicionales, que se muestran aquí: ZipFile(File f) throws ZipException, IOException
ZipFile(File f, int como) throws IOException
Cada uno abre el archivo ZIP especifi cado por f. El valor de cómo debe ser ZipFile.OPEN_READ
o
Cuando se especifi ca OPEN_DELETE, habrá de eliminarse el archivo ZIP. Sin embargo, aún podrá leer el archivo a través de la instancia de ZipFile abierta. Esta opción le permite borrar automáticamente un archivo ZIP después de que se ha descomprimido. Por ejemplo, si sustituye esta línea en el ejemplo, eliminará el archivo ZIP después de descomprimirlo:
zf = new ZipFile(new File(args[0]),
ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
Por supuesto, debe usar esta opción con cuidado porque borra el archivo ZIP, lo que signifi ca que no puede usarse nuevamente más adelante. Y un tema adicional: el segundo constructor también puede lanzar una ZipException.
Si quiere extraer una entrada específica de un archivo ZIP, puede llamar a getEntry( ) en la instancia de ZipFile. Aquí se muestra cómo:
ZipEntry getEntry(String nombreent)
El nombre de la entrada se pasa en nombreent. Se devuelve una ZipEntry para la entrada. Si ésta no se puede encontrar, se devuelve null.