zipentry read example java zip inputstream

read - La mejor manera de detectar si una secuencia está comprimida en Java



zipinputstream example (5)

¿Cuál es la mejor manera de descubrir que java.io.InputStream contiene datos comprimidos?


Los bytes mágicos para el formato ZIP son 50 4B . Podría probar el flujo (usando la mark y el reset , es posible que necesite un buffer ), pero no creo que este sea un enfoque 100% confiable. No habría manera de distinguirlo de un archivo de texto codificado en US-ASCII que comenzó con las letras PK .

La mejor manera sería proporcionar metadatos en el formato del contenido antes de abrir el flujo y luego tratarlos adecuadamente.


No muy elegante, pero confiable:

Si la secuencia se puede leer a través de ZipInputStream , debe estar comprimido.


Puede comprobar que los primeros cuatro bytes de la secuencia son la firma del encabezado del archivo local que inicia el encabezado del archivo local que procede a cada archivo en un archivo ZIP, como se muestra en la especificación aquí para que sea 50 4B 03 04 .

Un pequeño código de prueba muestra que esto funciona:

byte[] buffer = new byte[4]; try { ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip")); ZipEntry ze = new ZipEntry("HelloWorld.txt"); zos.putNextEntry(ze); zos.write("Hello world".getBytes()); zos.close(); FileInputStream is = new FileInputStream("so.zip"); is.read(buffer); is.close(); } catch(IOException e) { e.printStackTrace(); } for (byte b : buffer) { System.out.printf("%H ",b); }

Me dio esta salida:

50 4B 3 4


Verificar el número mágico puede no ser la opción correcta.

Los archivos Docx también tienen un número mágico similar 50 4B 3 4


Introducción

Como todas las respuestas tienen 5 años, siento el deber de anotar lo que está sucediendo hoy. ¡Dudo seriamente que uno debería leer bytes mágicos de la transmisión! Ese es un código de bajo nivel, debe ser evitado en general.

Respuesta simple

Miku escribe:

Si la secuencia se puede leer a través de ZipInputStream, debe estar comprimido.

Sí, pero en el caso de ZipInputStream "se puede leer" significa que la primera llamada a .getNextEntry() devuelve un valor no nulo. Sin excepción la captura etcétera. Así que en lugar de realizar un análisis de bytes mágicos puedes hacer:

boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;

¡Y eso es!

Pensamientos generales de descompresión

En general, parece que es mucho más conveniente trabajar con archivos mientras [un] zip, que con secuencias. Hay varias bibliotecas útiles, además ZipFile tiene más funcionalidad que ZipInputStream. El tratamiento de los archivos zip se explica aquí: ¿Qué es una buena biblioteca de Java para comprimir / descomprimir archivos? Así que si puedes trabajar con archivos es mejor que lo hagas!

Muestra de código

Necesitaba en mi aplicación trabajar solo con streams. Ese es el método que escribí para descomprimir:

import org.apache.commons.io.IOUtils; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public boolean unzip(InputStream inputStream, File outputFolder) throws IOException { ZipInputStream zis = new ZipInputStream(inputStream); ZipEntry entry; boolean isEmpty = true; while ((entry = zis.getNextEntry()) != null) { isEmpty = false; File newFile = new File(outputFolder, entry.getName()); if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) { FileOutputStream fos = new FileOutputStream(newFile); IOUtils.copy(zis, fos); IOUtils.closeQuietly(fos); } } IOUtils.closeQuietly(zis); return !isEmpty; }