web-dev-qa-db-fra.com

Lire le contenu des fichiers contenus dans le fichier Zip

J'essaie de créer un simple programme Java) qui lit et extrait le contenu du ou des fichiers contenus dans le fichier Zip. Le fichier Zip contient 3 fichiers (txt, pdf, docx). lis le contenu de tous ces fichiers et j’utilise Apache Tika à cette fin.

Quelqu'un peut-il m'aider ici pour atteindre la fonctionnalité. J'ai essayé jusqu'à présent mais sans succès

extrait de code

public class SampleZipExtract {


    public static void main(String[] args) {

        List<String> tempString = new ArrayList<String>();
        StringBuffer sbf = new StringBuffer();

        File file = new File("C:\\Users\\xxx\\Desktop\\abc.Zip");
        InputStream input;
        try {

          input = new FileInputStream(file);
          ZipInputStream Zip = new ZipInputStream(input);
          ZipEntry entry = Zip.getNextEntry();

          BodyContentHandler textHandler = new BodyContentHandler();
          Metadata metadata = new Metadata();

          Parser parser = new AutoDetectParser();

          while (entry!= null){

                if(entry.getName().endsWith(".txt") || 
                           entry.getName().endsWith(".pdf")||
                           entry.getName().endsWith(".docx")){
              System.out.println("entry=" + entry.getName() + " " + entry.getSize());
                     parser.parse(input, textHandler, metadata, new ParseContext());
                     tempString.add(textHandler.toString());
                }
           }
           Zip.close();
           input.close();

           for (String text : tempString) {
           System.out.println("Apache Tika - Converted input string : " + text);
           sbf.append(text);
           System.out.println("Final text from all the three files " + sbf.toString());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TikaException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
60
S Jagdeesh

Si vous vous demandez comment obtenir le contenu du fichier de chaque ZipEntry, c'est en fait assez simple. Voici un exemple de code:

public static void main(String[] args) throws IOException {
    ZipFile zipFile = new ZipFile("C:/test.Zip");

    Enumeration<? extends ZipEntry> entries = zipFile.entries();

    while(entries.hasMoreElements()){
        ZipEntry entry = entries.nextElement();
        InputStream stream = zipFile.getInputStream(entry);
    }
}

Une fois que vous avez le InputStream, vous pouvez le lire comme vous le souhaitez.

150
Rodrigo Sasaki

À partir de Java 7, l’API de NIO fournit un moyen plus générique d’accéder au contenu des fichiers Zip ou Jar. C’est désormais une API unifiée qui vous permet de traiter les fichiers Zip avec précision. comme des fichiers normaux.

Pour extraire tous les fichiers contenus dans un fichier Zip dans cette API, procédez comme suit:

In Java 8:

private void extractAll(URI fromZip, Path toDirectory) throws IOException{
    FileSystems.newFileSystem(fromZip, Collections.emptyMap())
            .getRootDirectories()
            .forEach(root -> {
                // in a full implementation, you'd have to
                // handle directories 
                Files.walk(root).forEach(path -> Files.copy(path, toDirectory));
            });
}

Dans Java 7:

private void extractAll(URI fromZip, Path toDirectory) throws IOException{
    FileSystem zipFs = FileSystems.newFileSystem(fromZip, Collections.emptyMap());

    for(Path root : zipFs.getRootDirectories()) {
        Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
                    throws IOException {
                // You can do anything you want with the path here
                Files.copy(file, toDirectory);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
                    throws IOException {
                // In a full implementation, you'd need to create each 
                // sub-directory of the destination directory before 
                // copying files into it
                return super.preVisitDirectory(dir, attrs);
            }
        });
    }
}
37
LordOfThePigs

En raison de la condition dans while, la boucle pourrait ne jamais se rompre:

while (entry != null) {
  // If entry never becomes null here, loop will never break.
}

Au lieu de la vérification null ici, vous pouvez essayer ceci:

ZipEntry entry = null;
while ((entry = Zip.getNextEntry()) != null) {
  // Rest of your code
}
10
Nishant Shreshth

Exemple de code que vous pouvez utiliser pour laisser Tika prendre en charge les fichiers de conteneur pour vous. http://wiki.Apache.org/tika/RecursiveMetadata

D'après ce que je peux dire, la solution acceptée ne fonctionnera pas dans les cas où il existe des fichiers Zip imbriqués. Tika, cependant, prendra en charge de telles situations.

3
Harinder

Pour ce faire, je crée une classe de wrapping ZipInputStream capable de fournir uniquement le flux de l’entrée actuelle:

La classe wrapper:

public class ZippedFileInputStream extends InputStream {

    private ZipInputStream is;

    public ZippedFileInputStream(ZipInputStream is){
        this.is = is;
    }

    @Override
    public int read() throws IOException {
        return is.read();
    }

    @Override
    public void close() throws IOException {
        is.closeEntry();
    }

}

L'utilisation de celui-ci:

    ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream("SomeFile.Zip"));

    while((entry = zipInputStream.getNextEntry())!= null) {

     ZippedFileInputStream archivedFileInputStream = new ZippedFileInputStream(zipInputStream);

     //... perform whatever logic you want here with ZippedFileInputStream 

     // note that this will only close the current entry stream and not the ZipInputStream
     archivedFileInputStream.close();

    }
    zipInputStream.close();

Un avantage de cette approche: les InputStreams sont passés comme arguments aux méthodes qui les traitent et ces méthodes ont tendance à fermer immédiatement le flux d’entrée après l’avoir terminé.

2
Vilius