2010-11-10 8 views
5

Nous avons besoin de déterminer si un InputStream entrant est une référence à un fichier zip ou à des données zip. Nous n'avons pas de référence à la source sous-jacente du flux. Nous visons à copier le contenu de ce flux dans un OutputStream dirigé vers un autre emplacement.Vérifier si un flux est un fichier zip

J'ai essayé de lire le flux en utilisant ZipInputStream et d'extraire un ZipEntry. Le ZipEntry est null si le flux est un fichier normal - comme prévu - cependant, en vérifiant un ZipEntry, je perds les deux premiers octets du flux. Par conséquent, au moment où je sais que le flux est un flux régulier, j'ai déjà perdu les données initiales du flux. Toute idée sur la façon de vérifier si InputStream est une archive sans perte de données serait utile.

Merci.

+0

Veuillez voir mes commentaires à la réponse par Galactus ci-dessous - qui est l'approche que je prends comme une résolution. Merci a tous. – AKS

+1

Bienvenue dans Stack Overflow! N'oubliez pas de marquer la réponse que vous avez choisie comme «sélectionnée» (le contour de la case à cocher sur la gauche). –

+0

Merci. Juste fait. – AKS

Répondre

6

En supposant que votre flux d'entrée d'origine n'est pas mis en mémoire tampon, j'essaierais d'encapsuler le flux d'origine dans un BufferedInputStream, avant de l'encapsuler dans un ZipInputStream à vérifier. Vous pouvez utiliser "mark" et "reset" dans le BufferedInputStream pour revenir à la position initiale dans le flux, après votre vérification.

+0

Merci. Je vais 'duh!'. Je suis sur le point d'essayer ça. – AKS

+0

Cela fonctionne. Je suis capable d'envelopper mon InputStream original en tant que BufferedInputStream, définir une marque, puis créer un ZipInputStream pour vérifier un ZipEntry. Un appel reset() et mon flux est prêt à être réutilisé. Maintenant, expérimenter avec la meilleure taille pour le tampon. Merci beaucoup ! – AKS

0

Cela ressemble un peu à un hack, mais vous pouvez implémenter un proxy java.io.InputStream pour s'asseoir entre ZipInputStream et le flux que vous avez initialement transmis au constructeur de ZipInputStream. Votre proxy deviendrait un tampon jusqu'à ce que vous sachiez s'il s'agit d'un fichier ZIP ou non. Sinon, le tampon enregistre votre journée.

+0

Oui, ça sonne comme un hack :) .. mais intéressant. Je suis sur le point d'essayer la suggestion de Galactus et d'essayer celle-ci si ça ne marche pas :) – AKS

0

Vous avez décrit un java.io.PushbackInputStream - en plus de read(), il a une unread(byte[]) qui vous permet de les pousser BCK à l'avant du flux, et de les read() re à nouveau.

C'est dans java.io depuis JDK1.0 (bien que j'avoue que je n'ai pas vu une utilisation pour cela jusqu'à aujourd'hui).

+0

J'ai essayé d'utiliser le PushbackInputStream. Cependant, l'acte de créer un ZipInputStream pour vérifier si le flux a un ZipEntry et est donc une archive, lit des octets en plus de la lecture du flux de refoulement - qui sont perdus à l'appel non lu(). – AKS

+0

@AKS: Attendez, vous ne pouvez pas envelopper le PBS dans ZS? Ce genre de défaites l'utilité du PBS :( – Piskvor

2

Vous pouvez vérifier les premiers octets du flux pour la signature d'en-tête local ZIP (PK 0x03 0x04), ce qui serait suffisant dans la plupart des cas. Si vous avez besoin de plus de précision, vous devriez prendre ~ 100 derniers octets et vérifier les champs de localisation du répertoire central.

+0

Oui, cela semblait être l'approche la plus apparente pour la vérification du flux.Cependant, je comprends, en fonction de l'outil utilisé pour créer le zip, l'en-tête pourrait différer. Par conséquent, bien que le contrôle le plus fiable, nous nous sommes éloignés de cela puisque nous ne voulions pas vérifier tous les en-têtes pkzip possibles. – AKS

+0

S'il vous plaît laissez-moi savoir si la différence dans les en-têtes basés sur des outils n'est pas le cas. – AKS

+2

Le standard ZIP a un critère fort pour le champ d'en-tête local zip, il doit donc avoir le même format pour toutes les archives zip. –

2

Voici comment je l'ai fait. Utilisation de mark/reset pour restaurer le flux si GZIPInputStream détecte un format zip incorrect (lève l'exception 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; 
    } 
} 
Questions connexes