2010-07-13 3 views
25

Je reçois un ZipInputStream d'une autre source, et j'ai besoin de fournir le InputStream de la première entrée à une autre source. J'espérais pouvoir le faire sans enregistrer un fichier temporaire sur un périphérique, mais la seule façon d'obtenir un InputStream pour une entrée individuelle est via ZipFile.getInputStream (entrée) et depuis j'ai un ZipInputStream et pas un ZipFile, ce n'est pas possible.est-il possible d'obtenir un flux d'entrée zipentry à partir d'un flux de sortie zip?

Donc, la meilleure solution que j'ai est

  1. Enregistrer InputStream entrant dans un fichier
  2. fichier de lecture en tant que fichier temporaire suppression InputStream
  3. d'entrée ZipFile
  4. de la première utilisation.

Répondre

31

figurés:

il est tout à fait possible, l'appel à ZipInputStream.getNextEntry() positionne le InputStream au début de l'entrée et donc fournit la ZipInputStream est l'équivalent de la fourniture d'un InputStream ZipEntry. Le ZipInputStream est assez intelligent pour gérer le flux descendant de l'entrée, ou du moins c'est ce que l'on pourrait croire.

p.

+3

Je ne comprends pas ce que vous voulez dire par là? Pouvez-vous ajouter un échantillon de code? – Whitecat

+3

Ce qu'il veut dire, c'est qu'un ZipInputStream peut être utilisé à la fois pour le zip et pour la lecture de chaque composant. .getNextEntry() passe au premier composant, le lit, fait un autre .getNextEntry() et votre flux est réinitialisé sur le second et ainsi de suite ... Clever, en fait. – akauppi

11

En plus de @pstanton, voici un exemple de code. J'ai résolu le problème en utilisant le code suivant. Il était difficile de comprendre ce que la réponse précédente sans un exemple.

//If you just want the first file in the zipped InputStream use this code. 
//Otherwise loop through the InputStream using getNextEntry() 
//till you find the file you want. 
private InputStream convertToInputStream(InputStream stream) throws IOException { 
    ZipInputStream zis = new ZipInputStream(stream); 
    zis.getNextEntry(); 
    return zis; 
} 

En utilisant ce code, vous pouvez renvoyer un InputStream du fichier compressé.

+0

Et après que le premier composant a été lu, on peut à nouveau '.getNextEntry()', pour lire le second. – akauppi

1

Le code postal est assez facile, mais j'ai eu des problèmes avec le retour de ZipInputStream comme Inputstream. Pour une raison quelconque, certains des fichiers contenus dans le fichier zip ont été supprimés. Le ci-dessous était ma solution et jusqu'ici son travail.

private Map<String, InputStream> getFilesFromZip(final DataHandler dhZ, 
     String operation) throws ServiceFault { 
    Map<String, InputStream> fileEntries = new HashMap<String, InputStream>(); 
    try { 
     ZipInputStream zipIsZ = new ZipInputStream(dhZ.getDataSource() 
     .getInputStream()); 

     try { 
      ZipEntry entry; 
      while ((entry = zipIsZ.getNextEntry()) != null) { 
       if (!entry.isDirectory()) { 
        Path p = Paths.get(entry.toString()); 
        fileEntries.put(p.getFileName().toString(), 
        convertZipInputStreamToInputStream(zipIsZ)); 
       } 
      } 
     } 
     finally { 
      zipIsZ.close(); 
     } 

    } catch (final Exception e) { 
     faultLocal(LOGGER, e, operation); 
    } 

    return fileEntries; 
} 
private InputStream convertZipInputStreamToInputStream(
final ZipInputStream in) throws IOException { 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    IOUtils.copy(in, out); 
    InputStream is = new ByteArrayInputStream(out.toByteArray()); 
    return is; 
} 
Questions connexes