Lecture d'un ZipInputStream dans un ByteArrayOutputStream
Je suis en train de lire un seul fichier à partir d'un java.util.zip.ZipInputStream
et le copier dans un java.io.ByteArrayOutputStream
(de sorte que je peux ensuite créer un java.io.ByteArrayInputStream
et la main qui à une 3ème partie de la bibliothèque qui prendra fin à la fermeture du flux, et je ne veux pas que mon ZipInputStream
arriver fermé).
Je suis probablement manque quelque chose de fondamental ici, mais je n'entrez jamais dans la boucle while ici:
ByteArrayOutputStream streamBuilder = new ByteArrayOutputStream();
int bytesRead;
byte[] tempBuffer = new byte[8192*2];
try {
while ((bytesRead = zipStream.read(tempBuffer)) != -1) {
streamBuilder.write(tempBuffer, 0, bytesRead);
}
} catch (IOException e) {
//...
}
Ce qui me manque qui va me permettre de copier le flux?
Edit:
Je devrais ai mentionné plus tôt que ce ZipInputStream
n'est pas venue à partir d'un fichier, donc je ne pense pas que je peux utiliser un ZipFile
. Il est à venir à partir d'un fichier téléchargé par l'intermédiaire d'un servlet.
Aussi, j'ai déjà appelé getNextEntry()
sur le ZipInputStream
avant d'arriver à cet extrait de code. Si je ne tente pas de copier le fichier dans un autre InputStream
(via le OutputStream
mentionné ci-dessus), et vient de passer le ZipInputStream
à mon 3ème partie de la bibliothèque, la bibliothèque ferme le flux, et je ne peux rien faire de plus, comme traiter avec les fichiers restants dans le flux.
source d'informationauteur pkaeding
Vous devez vous connecter pour publier un commentaire.
Votre boucle est valide - que fait le code suivant (seulement sur son propre) de retour?
si elle retourne -1, alors le zipStream est fermé avant de l'obtenir, et tous les paris sont éteints. Il est temps d'utiliser votre débogueur et assurez-vous que ce qui est passé pour vous est en fait valable.
Lorsque vous appelez getNextEntry(), est-il renvoyer une valeur, et est données à l'entrée significative (c'est à dire ne getCompressedSize() renvoie une valeur valide)? SI vous êtes juste en train de lire un fichier Zip qui n'ont pas de lecture anticipée zip entrées incorporée, ZipInputStream ne va pas travailler pour vous.
Quelques anecdotes concernant le format Zip:
Chaque fichier incorporé dans un fichier zip contient un en-tête. Cet en-tête peut contenir des informations utiles (comme la compression de la longueur du cours d'eau, c'est le décalage dans le fichier, CRC) - ou il peut contenir un peu de magie valeurs qui disent en substance: "L'information n'est pas dans le flux de données d'en-tête, vous devez vérifier la fermeture éclair post introductif'.
Chaque fichier zip puis a une table qui est attaché à la fin du fichier qui contient toutes les zip entrées, les données réelles. Le tableau à la fin est obligatoire, et les valeurs qu'il doit être correcte. En revanche, les valeurs ancrées dans le cours d'eau n'ont pas à être fournis.
Si vous utilisez ZipFile, il lit le tableau à la fin de la zip. Si vous utilisez ZipInputStream, je soupçonne que getNextEntry() tente d'utiliser les entrées intégrées dans le flux. Si ces valeurs ne sont pas spécifiées, puis ZipInputStream n'a aucune idée de combien de temps le flux pourrait être. Gonfler algorithme est auto résiliation (en fait vous n'avez pas besoin de savoir la non compressé longueur du flux de sortie dans le but de recouvrer l'intégralité de la sortie), mais il est possible que la version Java de ce lecteur ne supporte pas cette situation très bien.
Je dirais que c'est assez rare d'avoir un servlet retour d'un ZipInputStream (il est beaucoup plus courant de recevoir une inflatorInputStream si vous allez à recevoir du contenu compressé.
Vous avez probablement essayé de lecture à partir d'un
FileInputStream
comme ceci:Ce ne travail depuis une archive zip peut contenir plusieurs fichiers et vous avez besoin de spécifier le fichier à lire.
Vous pouvez utiliser java.util.zip.ZipFile et une bibliothèque comme IOUtils de Apache Commons IO ou ByteStreams de Goyave que vous aider à copier les flux.
Exemple:
J'utiliserais IOUtils de la chambre des communes io projet.
Vous pouvez implémenter votre propre wrapper autour de la ZipInputStream qui ignore close() et de la main hors de la bibliothèque tierce.
Vous êtes absent appel
ZipEntry entrée = (ZipEntry) zipStream.getNextEntry();
à la position du premier octet décompressé de la première entrée.
J'appellerais getNextEntry() sur le ZipInputStream jusqu'à ce qu'il est à l'entrée que vous souhaitez (ZipEntry.getName (), etc.). L'appel de getNextEntry() avance le "curseur" pour le début de l'entrée qu'il renvoie. Ensuite, utilisez ZipEntry.getSize() pour déterminer le nombre d'octets que vous devriez lire à l'aide de zipInputStream.read().
Il est difficile de savoir comment vous avez obtenu le zipStream. Il devrait fonctionner quand vous obtenez comme ceci:
t est difficile de savoir comment vous avez obtenu le zipStream. Il devrait fonctionner quand vous obtenez comme ceci:
Si vous êtes l'obtention de la ZipInputStream à partir d'un ZipFile vous pouvez obtenir un flux pour la 3d partie de la bibliothèque, permettre d'utiliser, et vous obtenez un autre flux d'entrée à l'aide du code avant.
Rappelez-vous, un inputstream est un curseur. Si vous disposez de l'ensemble des données (comme un ZipFile), vous pouvez demander pour N curseurs sur elle.
Un diferent cas est si vous avez seulement un "GZip" inputstream, seulement un zippé flux d'octets. Dans ce cas, vous ByteArrayOutputStream tampon rend tous les sens.
S'il vous plaît essayer de code soufflet
Vérifier si le flux d'entrée est positionné dans la mendicité.
Sinon, comme la mise en œuvre: je ne pense pas que vous devez écrire dans le flux de résultat au cours de la lecture, à moins que vous traitez exacte de ce flux dans un autre thread.
Il suffit de créer un tableau d'octets, lire le flux d'entrée, puis de créer le flux de sortie.