2010-11-10 8 views
5

Tenemos un requerimiento para determinar si un InputStream entrante es una referencia a un archivo zip o datos zip. No tenemos referencia a la fuente subyacente de la transmisión. Nuestro objetivo es copiar el contenido de esta secuencia en un OutputStream dirigido a una ubicación alternativa.Comprobando si una secuencia es un archivo zip

Intenté leer la secuencia usando ZipInputStream y extrayendo un ZipEntry. ZipEntry es nulo si la transmisión es un archivo normal, como se esperaba, sin embargo, al buscar un ZipEntry, pierdo el par inicial de bytes de la transmisión. Por lo tanto, cuando sé que la transmisión es una transmisión regular, ya he perdido los datos iniciales de la transmisión.

Cualquier idea sobre cómo comprobar si el InputStream es un archivo sin pérdida de datos sería útil.

Gracias.

+0

Por favor, consulte mis comentarios a la respuesta de Galactus a continuación - que es el enfoque que estoy tomando como una resolución. Gracias a todos. – AKS

+1

¡Bienvenido a Stack Overflow! No olvide marcar la respuesta que eligió como "seleccionada" (el contorno de la marca de verificación a la izquierda). –

+0

Gracias. Acaba de hacer. – AKS

Respuesta

6

Suponiendo que la intensidad de entrada original no está en el búfer, trataría de envolver la secuencia original en un BufferedInputStream, antes de envolverlo en un ZipInputStream para verificar. Puede usar "marcar" y "reiniciar" en BufferedInputStream para volver a la posición inicial en la transmisión, después de su verificación.

+0

Gracias. Voy a 'duh!'. Estoy a punto de probar esto. – AKS

+0

Esto funciona. Puedo envolver mi InputStream original como un BufferedInputStream, establecer una marca y luego crear un ZipInputStream para comprobar si hay una entrada Zip. Una llamada de reinicio() y mi transmisión está lista para su reutilización. Ahora, experimentando con el mejor tamaño para el buffer. Muchas gracias ! – AKS

0

Suena un poco como un truco, pero podría implementar un proxy java.io.InputStream para sentarse entre ZipInputStream y la secuencia que originalmente pasó al constructor de ZipInputStream. Su proxy se transmitirá a un búfer hasta que sepa si es un archivo ZIP o no. Si no, entonces el buffer salva tu día.

+0

Sí, suena como un truco :) .. pero interesante. Estoy a punto de probar la sugerencia de Galactus y probar esta si eso no funciona :) – AKS

0

Usted ha descrito un java.io.PushbackInputStream - además de read(), tiene una unread(byte[]) que permite les mueves Pienso volver a la parte delantera de la corriente, y para volver a read() nuevo.

Está en java.io desde JDK1.0 (aunque admito que no he visto un uso hasta el día de hoy).

+0

Intenté usar PushbackInputStream. Sin embargo, el acto de crear un ZipInputStream para verificar si el flujo tiene un ZipEntry y, por lo tanto, es un archivo, lee bytes además de la lectura de la corriente Pushback, que se pierden para la llamada no leída(). – AKS

+0

@AKS: ¿Espera, entonces no puedes envolver el PBS en ZS? Ese tipo de derrotas la utilidad de PBS :( – Piskvor

2

Puede verificar los primeros bytes de la secuencia para la firma del encabezado local ZIP (PK 0x03 0x04), eso sería suficiente para la mayoría de los casos. Si necesita más precisión, debería tomar los últimos ~ 100 bytes y verificar los campos de localización del directorio central.

+0

Sí, este parece ser el enfoque más evidente para la verificación de la secuencia.Sin embargo, entiendo, dependiendo de la herramienta utilizada para crear el zip, el encabezado podría ser diferente. Por lo tanto, aunque el cheque más confiable, nos alejamos de esto ya que no queríamos comprobar cada posible encabezado de pkzip. – AKS

+0

Háganme saber si la diferencia en los encabezados en función de las herramientas no es el caso. – AKS

+2

El estándar ZIP tiene un criterio estricto para el campo de encabezado zip local, por lo que debe tener el mismo formato para todos los archivos comprimidos. –

2

Así es como lo hice.

Usando mark/reset para restaurar la transmisión si GZIPInputStream detecta un formato zip incorrecto (arroja la excepción ZipException).

/** 
* Wraps the input stream with GZIPInputStream if needed. 
* @param inputStream 
* @return 
* @throws IOException 
*/ 
private InputStream wrapIfZip(InputStream inputStream) throws IOException { 
    if (!inputStream.markSupported()) { 
     inputStream = new BufferedInputStream(inputStream); 
    } 
    inputStream.mark(1000); 
    try { 
     return new GZIPInputStream(inputStream); 
    } catch (ZipException e) { 
     inputStream.reset(); 
     return inputStream; 
    } 
} 
Cuestiones relacionadas