2014-01-20 3 views
0

У меня есть несколько файлов zip, каждый из которых содержит несколько файлов, которые я хочу извлечь, используя класс ZipInputStream. Среди них некоторые изображения. Когда я пытаюсь извлечь эти изображения с помощью BufferedOutputStream, они частично распаковываются, а изображения неполны.Я не могу полностью извлечь zip-файлы, используя ZipInputStream

private void extractArchives() { 

    ZipInputStream zis; 

    File archiveDir = new File(
      Environment.getExternalStorageDirectory().getAbsolutePath() + 
    "/archives/"); 

    File[] files = archiveDir.listFiles(); 

    for (int i = 0; i < files.length; ++i) 
    { 
     File file = files[i]; 

     try 
     { 
      zis = new ZipInputStream(new FileInputStream(file)); 
      ZipEntry ze; 

      while ((ze = zis.getNextEntry()) != null) 
      { 
       BufferedOutputStream bos; 
       byte[] buffer = new byte[102400]; 
       int count; 

       while ((count = zis.read(buffer)) != -1) 
       { 
        String fileName = ze.getName(); 

        if (fileName.endsWith(".jpg")) 
        { 
         path += File.separator + fileName; 
         bos = new BufferedOutputStream(new FileOutputStream(path)); 
         bos.write(buffer, 0, count); 
         bos.close(); 
        } 
       } 
      } 

      zis.close(); 

     } 

     catch(FileNotFoundException e) { continue; } 

     //If the file is not a zip file or is a directory 
     catch (IOException e) { continue; } 

    } 
} 

Есть ли что-то неправильное с кодом выше? Использует ли BufferedOutputStream эту проблему? Я ценю любые идеи. Благодарю.

+0

Где переменные 'files',' 'path' и zis' объявили? У вас есть одна явная проблема в вашем источнике, помимо вашей проблемы с распаковкой: вы всегда добавляете свой путь («путь + = файл.сепаратор + имя_файла»), поэтому имя пути увеличивается дольше, но вы не создаете никаких новых каталогов. –

+0

Да, ты прав. Я должен это исправить. Однако я попытался с одним zip-файлом и одним изображением в нем, и все же изображение не полностью извлечено. –

ответ

0

Сфокусированный на цикле, который выполняет итерацию по записям zip, проблема в том, что вы читали не более 102400 байт из записи zip и затем записывали это в новый файл. Следующий максимум 102400 байт, если один и тот же файл изображения был записан в новый файл. Если имя пути было таким же, как старый файл, оно перезаписало бы старый файл. Но поскольку вы постоянно добавляли локальный переменный «путь», я не уверен, где данные оказались.

Отверните открытие FileOutputStream из внутреннего цикла и продолжайте писать в тот же OutputStream, пока не сможете прочитать больше байтов из текущего ZipEntry. Только затем перейдите к следующему ZipEntry и следующему OutputStream.

Это стандартный шаблон для чтения и копирования между потоками в Java, так что я могу исправить код, не имея определения files, path и zis, но это поможет, если вы можете оставить реальный пример компиляции коды так, чтобы другие люди тоже могут воспользоваться этим.

Еще одно усовершенствование, которое вам нужно в производственном коде, состоит в том, чтобы обернуть bos.close() в блок try/finally, чтобы выходной файл также был закрыт, если при чтении с входа было исключение.

 while ((ze = zis.getNextEntry()) != null) { 
      String fileName = ze.getName(); 

      if (fileName.endsWith(".jpg")) { 
       String filepath = path + File.separator + fileName; 
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filepath)); 
       byte[] buffer = new byte[102400]; 
       int count; 
       while ((count = zis.read(buffer)) != -1) { 
        bos.write(buffer, 0, count); 
       } 
       bos.close(); 
      } 
     } 
1

Я изменил способ в соответствии с тем, что сказал Эрвин и теперь он работает:

private void extractArchives() { 

    File archiveDir = new File(
       Environment.getExternalStorageDirectory().getAbsolutePath() + 
       "/archives/"); 

    String archivePath = archiveDir.getAbsolutePath(); 

    File[] files = archiveDir.listFiles(); 

    for (int i = 0; i < files.length; ++i) 
    { 
     File file = files[i]; 

     if(!file.isDirectory()) 
     { 
      try { 

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

       while (entry != null) 
       { 
        if(entry.getName().endsWith(".jpg")) 
        { 
         String imagePath = themePath + File.separator + entry.getName(); 

         BufferedOutputStream bos = new BufferedOutputStream(
            new FileOutputStream(imagePath)); 

         byte[] buffer = new byte[4096]; 

         int read = 0; 

         while ((read = zis.read(buffer)) != -1) bos.write(buffer, 0, read); 

         imagePath = ""; 

         bos.close(); 
        } 

        zis.closeEntry(); 

        entry = zis.getNextEntry(); 
       } 

       zis.close(); 
      } 

      catch (FileNotFoundException e) {} 

      catch (IOException e) {} 
     } 
    } 
} 
+0

Можете ли вы принять мой ответ, если считаете, что он правильный? –

+0

Как насчет вас? Я упомянул вас в своем ответе. Слишком великодушно принять! :)) –

Смежные вопросы