2009-07-30 29 views
17

Estoy utilizando el paquete de utilidad Zip de Java y quería saber cómo crear un archivo zip sin compresión. Establecer el nivel a 0 no ayuda. ¿Es esto correcto?Cómo crear un archivo Zip sin comprimir en Java

Además, cuando he utilizado el método STORED, que arroja siguiente excepción:

java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32 

puedo configurar el tamaño pero ahora excepción siguiente:

java.util.zip.ZipException: invalid entry crc-32 

sólo estoy siguiendo todas las ejemplos disponibles buscando en la web y no soy capaz de realmente entenderlo correctamente, supongo. Sería genial si alguien me puede ayudar con esto y darme una sugerencia para corregir el problema que podría estar haciendo.

+0

Esas constantes int son "un acento de código" de otra época (probablemente C) ... Me gustaría que David Connelly hubiera leído sobre las enumeraciones de Java antes de escribir ZipOutputStream. –

+0

@ChristopheRoussy Eso hubiera sido bastante difícil, ya que 'ZipOutputStream' apareció muchos años antes de las enumeraciones. – EJP

Respuesta

7

Es necesario utilizar el método STORED, pero esto requiere que establezca los size, compressedSize y crc32 propiedades de la correspondiente ZipEntry antes de poder llamar putNextEntry en el ZipOutputStream. Puede calcular previamente el CRC-32 utilizando un Crc32OutputStream.

+0

Gracias, parece que está en lo correcto, pero ¿está documentado en algún lugar? – AlexWien

+1

Se especifica en la Especificación de formato de archivo ZIP en https://www.pkware.com/documents/casestudies/APPNOTE.TXT. –

+1

@AlexWien Se generará un error por 'ZipOutputStream' si no lo hace ... afortunadamente recibió un buen mensaje de error. –

11

Desconfío de aperkins solución (ya eliminado), pero sé por qué funcionó. La línea (que desde entonces ha sido corregido en su respuesta)

zipOut.setLevel(ZipOutputStream.STORED); // accidentally right 

estaba usando el valor estático ZipOutputStream.STORED, lo que equivale a una coincidencia 0. Entonces, lo que esa línea está haciendo es establecer el nivel usado por el método DEFLATED predeterminado para cero compresión (esto es obviamente lo que quiere hacer, pero pasó a funcionar solo por suerte). Así que para obtener lo que desea de forma explícita y segura, utilizar esto en su lugar:

zipOut.setMethod(ZipOutputStream.DEFLATED); // this line optional 
zipOut.setLevel(0); 

o

zipOut.setLevel(Deflater.NO_COMPRESSION); 

Si utiliza

zipOut.setMethod(ZipOutputStream.STORED); 
zipOut.setLevel(Deflater.NO_COMPRESSION); 

probablemente obtendrá la excepción de que se señala en Keya la pregunta original. Creo que Christian Schlichtherle tiene razón; está obteniendo las Excepciones porque no está configurando el CRC en la entrada. Las repercusiones de esto es que para usar el método ALMACENADO, primero debe leer todo el archivo de entrada, o buscar otra forma de establecer el tamaño, el tamaño comprimido (debe ser igual) y el CRC antes de llamar al zipOut.putNextEntry(). De lo contrario, se encontrará con más excepciones si sobrepasa el atributo de tamaño escribiendo demasiados bytes en la secuencia de salida. Parece que las especificaciones ZIP dicen que si estás escribiendo datos almacenados, entonces tiene que escribir el encabezado [que incluye el CRC-32 y la longitud] "por adelantado" antes de los datos, por lo tanto, la API java que los requiere se establece antes puede comenzar, ya que básicamente solo admite la transmisión al archivo zip final.

+2

DEFLATED + Nivel (0) resultó en mi caso a ... CADA archivo comprimido (un poco) más grande que el archivo de origen: O estoy bastante seguro de desinflado-0 es diferente de la TIENDA:/desinflado –

+2

-0 y TIENDA _might_ ser diferente, pero tienen el mismo objetivo: un archivo comprimido que contiene datos sin comprimir. No espero que ninguno de los métodos genere un archivo de igual tamaño que el archivo fuente. Sin embargo, en la pregunta, Keya estaba teniendo problemas para usar el método STORE, debido al preprocesamiento requerido para obtener los argumentos requeridos. Si desea un archivo comprimido que sea más pequeño que el archivo fuente, use un valor diferente en setLevel(), pero eso no es lo que la pregunta estaba pidiendo. – PMorganCA

4

FYI:

En el JDK Fuente del método [java.util.zip.ZipOutputStream.setLevel (int)]:

public void setLevel(int level) { 
    def.setLevel(level); 
} 

simplemente redirigir el ajuste del nivel de compresión a la variable de campo [ def], que es una instancia de [java.util.zip.Deflater].

Y en el código fuente de la clase [java.util.zip.Deflater]:

/** 
* Compression level for no compression. 
*/ 
public static final int NO_COMPRESSION = 0; 

/** 
* Compression level for fastest compression. 
*/ 
public static final int BEST_SPEED = 1; 

/** 
* Compression level for best compression. 
*/ 
public static final int BEST_COMPRESSION = 9; 

/** 
* Default compression level. 
*/ 
public static final int DEFAULT_COMPRESSION = -1; 

lo tanto, yo creo que será más fácil de leer si se utiliza el valor constante [Deflater.NO_COMPRESSION]:

Cuestiones relacionadas