2016-02-11 23 views
6

Wiem, że Oracle zauważa kompresor/dekompresor plików ZIP/GZIP on their website. Ale mam scenariusz, w którym muszę skanować i dowiedzieć się, czy w grę wchodzą zagnieżdżone ZIP/RAR. Na przykład, następujący przypadek:Biblioteka narzędzi Java dla obsługi plików zagnieżdżonych ZIP

-MyFiles.zip 
    -MyNestedFiles.zip 
     -MyMoreNestedFiles.zip 
      -MoreProbably.zip 
     -Other_non_zips 
    -Other_non_zips 
-Other_non_zips 

wiem, że Apache Commons kompresować pakiet i java.util.zip są wideley stosowane pakiety gdzie fotografia kompresji rzeczywiście przeznaczony dla brakujących funkcji w java.util.zip np niektóre ustawienia postaci podczas robienia zipoutów. Ale nie jestem pewien, czy narzędzia do rekursji za pomocą zagnieżdżonych plików zip, a odpowiedzi dostarczone na SO nie są bardzo dobrym przykładem na to. Próbowałem następujący kod (który dostałem od Oracle blogu), ale podejrzewałem, zagnieżdżona rekurencji katalog nie dlatego, że po prostu nie może znaleźć pliki:

public static void processZipFiles(String pathName) throws Exception{ 
     ZipInputStream zis = null; 
     InputStream is = null; 
     try { 
      ZipFile zipFile = new ZipFile(new File(pathName)); 
      String nestPathPrefix = zipFile.getName().substring(0, zipFile.getName().length() -4); 
      for(Enumeration e = zipFile.entries(); e.hasMoreElements();){ 
      ZipEntry ze = (ZipEntry)e.nextElement(); 
      if(ze.getName().contains(".zip")){ 
       is = zipFile.getInputStream(ze); 
       zis = new ZipInputStream(is); 
       ZipEntry zentry = zis.getNextEntry(); 

       while (zentry!=null){ 
        System.out.println(zentry.getName()); 
        zentry = zis.getNextEntry(); 
        ZipFile nestFile = new ZipFile(nestPathPrefix+"\\"+zentry.getName()); 
        if (zentry.getName().contains(".zip")) { 
         processZipFiles(nestPathPrefix+"\\"+zentry.getName()); 
        } 
       } 
       is.close(); 
      } 
      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally{ 
      if(is != null) 
       is.close(); 
      if(zis!=null) 
       zis.close(); 
     } 
    } 

Może robie coś źle - albo za pomocą niewłaściwe utils. Moim celem jest zidentyfikowanie, czy któryś z plików lub zagnieżdżonych plików zip ma rozszerzenia plików, na które nie pozwalam. Ma to na celu uniemożliwienie moim użytkownikom przesyłania zabronionych plików, nawet gdy są one zapakowane. Mam także opcję korzystania z Tiki, która może wykonywać rekursywne parsowanie (używając rozwiązania Zukka Zitting), ale nie jestem pewien, czy mogę użyć metadanych do wykonania tego wykrycia, jak chcę.

Każda pomoc/sugestia jest doceniana.

+0

nie powinien pan być otwarcie zagnieżdżonego Zip ze strumienia wejściowego zewnętrznego zip, zamiast nazwy pliku (który nie będzie działał, ponieważ plik znajduje się w pliku zip nie w systemie plików)? – Gagravarr

Odpowiedz

2

Korzystanie Commons Compress byłoby łatwiejsze, nie tylko dlatego, że ma rozsądne współdzielone interfejsy między różnymi dekompresorów które czynią życie łatwiejszym + umożliwia manipulowanie innych formatów kompresji (np Tar) jednocześnie

Jeżeli chcesz używać tylko wbudowaną obsługę Zip, sugeruję zrobić coś takiego:

File file = new File("outermost.zip"); 
FileInputStream input = new FileInputStream(file); 
check(input, file.toString()); 

public static void check(InputStream compressedInput, String name) { 
    ZipInputStream input = new ZipInputStream(compressedInput); 
    ZipEntry entry = null; 
    while ((entry = input.getNextEntry()) != null) { 
     System.out.println("Found " + entry.getName() + " in " + name); 
     if (entry.getName().endsWith(".zip")) { // TODO Better checking 
     check(input, name + "/" + entry.getName()); 
     } 
    } 
} 

Twój kod nie powiedzie się, jak starasz się czytać inner.zip ciągu outer.zip jako lokalnego pliku, ale nie robi” t istnieje jako samodzielny plik. Powyższy kod będzie przetwarzać rzeczy kończąc .zip jako inny plik zip, a recurse

prawdopodobnie chcesz używać commons kompresować chociaż, więc można obsługiwać rzeczy z alternatywnymi nazwami, inne formaty kompresji itp

+0

Jest to proste rozwiązanie, ale nie jest rekompensowane przez .RAR. Próbowałem z Tiką, ale parsowanie metadanych zajmuje dużo czasu (prawdopodobnie dlatego, że analizuje całą sprawę). – ha9u63ar

+0

Widzę, że mogę zamienić ZipInputStream na 'ZipArchiveInputStream', ale którego strumienia używam dla RAR/TAR. Czy powinienem przechowywać 'ArchiveInputStream' i' ArchiveEntry' przez całą drogę? – ha9u63ar

+0

Jeśli chcesz pracować ze wszystkimi formatami przy użyciu funkcji Kompresuj Commons, użyj ogólnych klas archiwów. Aby to zrobić, zobacz kod źródłowy parsera pakietów Apache Tika (https://git1-us-west.apache.org/repos/asf?p=tika.git;a=blob;f=tika -parsers/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java; hb = HEAD) – Gagravarr