Как программно разархивировать файлы в Android?

Мне нужен небольшой фрагмент кода, который распаковывает несколько файлов из данного ZIP-файла и предоставляет отдельные файлы в соответствии с форматом, в котором они были в заархивированном файле. Пожалуйста, поделитесь своими знаниями и помогите мне.


person Kartik    schedule 01.08.2010    source источник
comment
Вы можете получить решение Kotlin здесь - stackoverflow.com/a/50990992/1162784   -  person arsent    schedule 22.06.2018


Ответы (14)


Была немного оптимизирована версия Пено. Заметно увеличение производительности.

private boolean unpackZip(String path, String zipname)
{       
     InputStream is;
     ZipInputStream zis;
     try 
     {
         String filename;
         is = new FileInputStream(path + zipname);
         zis = new ZipInputStream(new BufferedInputStream(is));          
         ZipEntry ze;
         byte[] buffer = new byte[1024];
         int count;

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

             // Need to create directories if not exists, or
             // it will generate an Exception...
             if (ze.isDirectory()) {
                File fmd = new File(path + filename);
                fmd.mkdirs();
                continue;
             }

             FileOutputStream fout = new FileOutputStream(path + filename);

             while ((count = zis.read(buffer)) != -1) 
             {
                 fout.write(buffer, 0, count);             
             }

             fout.close();               
             zis.closeEntry();
         }

         zis.close();
     } 
     catch(IOException e)
     {
         e.printStackTrace();
         return false;
     }

    return true;
}
person Vasily Sochinsky    schedule 12.06.2012
comment
‹Использует-разрешение android: name = android.permission.WRITE_EXTERNAL_STORAGE /› - person Lou Morda; 28.07.2012
comment
как вы думаете, этот же код работает для распаковки или распаковки obb файлов расширения APK Expansion Files? - person LOG_TAG; 02.08.2012
comment
Думаю, да, это работает, потому что это очень обычный способ распаковки вещей. Просто постарайтесь получить правильный путь и имя почтового индекса. Я также видел кое-что, что может вас заинтересовать (хотя, конечно, вы это уже видели): ссылка - person Vasily Sochinsky; 03.08.2012
comment
Потому что вам нужно пропустить операции с файлами, если ваш ze является каталогом. Попытка выполнить эти операции вызовет исключение. - person Vasily Sochinsky; 13.05.2013
comment
Почему бы вам не сделать этот метод статическим? Это сработает? - person felixd; 23.10.2013
comment
Это потрясающе. Раньше я использовал тот же ZipInputStream, но другое решение, и на распаковку файла размером 2 МБ требовалось 140 секунд. Теперь это в реальном времени, спасибо !! - person Tom; 21.07.2014
comment
Хорошая скорость, метод допинга, но верна ли эта потрясающая скорость? - person ; 23.11.2015
comment
Будет ли это работать с папками или только с файлами? А если нет, то как распаковать папки? - person praxmon; 26.02.2016
comment
Этот ответ не должен работать, потому что он не создает недостающие файлы для записи в них данных !! - person Omar HossamEldin; 17.11.2016
comment
На самом деле, этот код не будет работать, если zip-файл создается без пути нежелательной почты, например, вы можете запустить этот код, чтобы распаковать файл APK, вы получите FileNotFoundException. - person Shaw; 17.05.2017
comment
Я согласен с @Shaw. Если zip-архив был создан без записей каталога, он не будет работать. Каждый файл следует проверить, существует ли каталог, в который он должен быть извлечен. zip -j не будет создавать записи в каталоге. РЕДАКТИРОВАТЬ: на самом деле не заметил, но следующий ответ от zapi правильный. - person Krystian; 05.06.2017
comment
Обратите внимание, как указано @Shaw: если ваш ZIP-файл не содержит явных папок, такой метод завершится с ошибкой FileNotFoundException, поскольку в нем отсутствует новый файл (путь + File.separator + filename) .getParentFile (). Mkdirs () в ! isDirectory () ветвь - person Nicola Beghin; 23.03.2019
comment
Разве использование BufferedOutputStream(FileOutputStream) не будет быстрее, чем использование самого FileOutputStream? - person El Sushiboi; 30.04.2020

На основе ответа Василия Сочинского, немного измененного и с небольшим исправлением:

public static void unzip(File zipFile, File targetDirectory) throws IOException {
    ZipInputStream zis = new ZipInputStream(
            new BufferedInputStream(new FileInputStream(zipFile)));
    try {
        ZipEntry ze;
        int count;
        byte[] buffer = new byte[8192];
        while ((ze = zis.getNextEntry()) != null) {
            File file = new File(targetDirectory, ze.getName());
            File dir = ze.isDirectory() ? file : file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs())
                throw new FileNotFoundException("Failed to ensure directory: " +
                        dir.getAbsolutePath());
            if (ze.isDirectory())
                continue;
            FileOutputStream fout = new FileOutputStream(file);
            try {
                while ((count = zis.read(buffer)) != -1)
                    fout.write(buffer, 0, count);
            } finally {
                fout.close();
            }
            /* if time should be restored as well
            long time = ze.getTime();
            if (time > 0)
                file.setLastModified(time);
            */
        }
    } finally {
        zis.close();
    }
}

Заметные различия

  • public static - это статический служебный метод, который может быть где угодно.
  • 2 File параметра, потому что String: / для файлов, и нельзя было указать, куда должен быть извлечен zip-файл раньше. Также path + filename конкатенация> https://stackoverflow.com/a/412495/995891
  • throws - потому что поймать поздно - добавьте пробный улов, если действительно они не интересуют.
  • actually makes sure that the required directories exist in all cases. Not every zip contains all the required directory entries in advance of file entries. This had 2 potential bugs:
    • if the zip contains an empty directory and instead of the resulting directory there is an existing file, this was ignored. The return value of mkdirs() is important.
    • может аварийно завершить работу с zip-файлами, не содержащими каталогов.
  • увеличенный размер буфера записи, это должно немного улучшить производительность. Хранилище обычно находится в блоках по 4 КБ, а запись меньшими кусками обычно выполняется медленнее, чем необходимо.
  • использует магию finally для предотвращения утечки ресурсов.

So

unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));

должен делать эквивалент оригинала

unpackZip("/sdcard/", "pictures.zip")
person zapl    schedule 20.11.2014
comment
привет, я получаю путь с обратной косой чертой, например sdcard / temp / 768 \ 769.json, поэтому я получаю сообщение об ошибке, вы можете сказать мне, как с этим справиться - person Ando Masahashi; 17.12.2014
comment
@AndoMasahashi, который должен быть допустимым именем файла в файловой системе Linux. Какую ошибку вы получаете и как должно выглядеть имя файла в конце? - person zapl; 17.12.2014
comment
он выглядит как /sdcard/pictures\picturess.jpeg и файл ошибки не найден ошибка - person Ando Masahashi; 18.12.2014
comment
Он работает нормально, но выдает исключение, когда одно из имен файлов внутри zip не находится в UTF8 format. Итак, я использовал этот код вместо этого, который использует commons-compress lib apache. - person Ashish Tanna; 30.07.2015
comment
@AshishTanna действительно, это известная проблема blogs.oracle.com/xuemingshen/entry - person zapl; 30.07.2015
comment
Привет, у меня было это, что это такое и как решить эту проблему, пожалуйста, помогите мне, java.util.zip.ZipException: несоответствие CRC - person Vijay; 21.08.2017
comment
@Vijaykumar, вероятно, ваш почтовый индекс поврежден. Может быть, как в stackoverflow.com/questions/11058639/ вы загрузили неправильно. А может вы просто вставили битый zip-файл. Снимите файл с устройства и убедитесь, что он работает, с помощью инструмента распаковки на рабочем столе. - person zapl; 21.08.2017
comment
@Vijaykumar Раздел комментариев - плохое место, чтобы много спрашивать / отлаживать. Пожалуйста, опубликуйте новый вопрос, показывающий, как вы получаете zip-файл на устройство. Возможно, ссылка на фактический файл, чтобы люди могли воспроизвести вашу ошибку. Ошибка CRC означает, что контрольная сумма извлеченного файла не соответствует тому, что указано в zip-файле, поэтому что-то в заархивированных данных обычно неверно. Это означает, что вам нужно посмотреть на файл и на то, что с ним произойдет, прежде чем он попадет в приведенный выше код. - person zapl; 22.08.2017
comment
Есть ли способ проверить, достаточно ли на устройстве пользователя места для распаковки файла? Что произойдет в настоящее время, если они этого не сделают? - person Charlie; 06.07.2018
comment
Итак, в приведенном выше коде файл pictures.zip хранится в папке sdcard. И когда мы его распакуем, он будет храниться в той же папке sdcard? Или вне папки sdcard? Я хотел, чтобы расположение файла в zip-архиве и расположение распакованного файла совпадали! Это сработает? Если да, не приведет ли это к сбою, поскольку в той же папке будет находиться мой zip-файл. - person Prajwal Waingankar; 10.09.2019

Это мой метод распаковки, который я использую:

private boolean unpackZip(String path, String zipname)
{       
     InputStream is;
     ZipInputStream zis;
     try 
     {
         is = new FileInputStream(path + zipname);
         zis = new ZipInputStream(new BufferedInputStream(is));          
         ZipEntry ze;

         while((ze = zis.getNextEntry()) != null) 
         {
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             byte[] buffer = new byte[1024];
             int count;

             String filename = ze.getName();
             FileOutputStream fout = new FileOutputStream(path + filename);

             // reading and writing
             while((count = zis.read(buffer)) != -1) 
             {
                 baos.write(buffer, 0, count);
                 byte[] bytes = baos.toByteArray();
                 fout.write(bytes);             
                 baos.reset();
             }

             fout.close();               
             zis.closeEntry();
         }

         zis.close();
     } 
     catch(IOException e)
     {
         e.printStackTrace();
         return false;
     }

    return true;
}
person petrnohejl    schedule 14.09.2011
comment
как вы думаете, этот же код работает для распаковки или распаковки obb файлов расширения APK Expansion Files? - person LOG_TAG; 02.08.2012

Котлинский путь

//FileExt.kt

data class ZipIO (val entry: ZipEntry, val output: File)

fun File.unzip(unzipLocationRoot: File? = null) {

    val rootFolder = unzipLocationRoot ?: File(parentFile.absolutePath + File.separator + nameWithoutExtension)
    if (!rootFolder.exists()) {
       rootFolder.mkdirs()
    }

    ZipFile(this).use { zip ->
        zip
        .entries()
        .asSequence()
        .map {
            val outputFile = File(rootFolder.absolutePath + File.separator + it.name)
            ZipIO(it, outputFile)
        }
        .map {
            it.output.parentFile?.run{
                if (!exists()) mkdirs()
            }
            it
        }
        .filter { !it.entry.isDirectory }
        .forEach { (entry, output) ->
            zip.getInputStream(entry).use { input ->
                output.outputStream().use { output ->
                    input.copyTo(output)
                }
            }
        }
    }

}

Использование

val zipFile = File("path_to_your_zip_file")
file.unzip()
person arsent    schedule 22.06.2018
comment
Он генерирует исключение в строке output.outputStream (), в котором говорится, что FileNotFoundException ... (не каталог) - person hamza khan; 16.11.2020

Android имеет встроенный Java API. Ознакомьтесь с пакетом java.util.zip.

Вам следует изучить класс ZipInputStream. Прочтите ZipEntry из ZipInputStream и скопируйте его в файловую систему / папку. Посмотрите аналогичный пример для сжатия в zip файл.

person ankitjaininfo    schedule 01.08.2010
comment
Вы должны были предоставить пример кода. Вы упустили много очков. - person Cameron Lowell Palmer; 23.02.2017

Хотя ответы, которые уже здесь, работают хорошо, я обнаружил, что они были немного медленнее, чем я ожидал. Вместо этого я использовал zip4j, который я считаю лучшим решением из-за его скорости. Это также позволило использовать различные параметры степени сжатия, что я нашел полезными.

person jcw    schedule 23.05.2013

используйте следующий класс

    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import android.util.Log;

    public class DecompressFast {



 private String _zipFile; 
  private String _location; 
 
  public DecompressFast(String zipFile, String location) { 
    _zipFile = zipFile; 
    _location = location; 
 
    _dirChecker(""); 
  } 
 
  public void unzip() { 
    try  { 
      FileInputStream fin = new FileInputStream(_zipFile); 
      ZipInputStream zin = new ZipInputStream(fin); 
      ZipEntry ze = null; 
      while ((ze = zin.getNextEntry()) != null) { 
        Log.v("Decompress", "Unzipping " + ze.getName()); 
 
        if(ze.isDirectory()) { 
          _dirChecker(ze.getName()); 
        } else { 
          FileOutputStream fout = new FileOutputStream(_location + ze.getName()); 
         BufferedOutputStream bufout = new BufferedOutputStream(fout);
          byte[] buffer = new byte[1024];
          int read = 0;
          while ((read = zin.read(buffer)) != -1) {
              bufout.write(buffer, 0, read);
          }

          
          
          
          bufout.close();
          
          zin.closeEntry(); 
          fout.close(); 
        } 
         
      } 
      zin.close(); 
      
      
      Log.d("Unzip", "Unzipping complete. path :  " +_location );
    } catch(Exception e) { 
      Log.e("Decompress", "unzip", e); 
      
      Log.d("Unzip", "Unzipping failed");
    } 
 
  } 
 
  private void _dirChecker(String dir) { 
    File f = new File(_location + dir); 
 
    if(!f.isDirectory()) { 
      f.mkdirs(); 
    } 
  } 


 }

Как пользоваться

 String zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip file location
    String unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; // destination folder location
  DecompressFast df= new DecompressFast(zipFile, unzipLocation);
    df.unzip();

Разрешения

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
person Manohar    schedule 19.10.2016
comment
может видеть имя файла, но при попытке извлечь файл я получаю ошибку FileNotFoundException - person Parth Anjaria; 20.06.2017

Согласно ответу @zapl, разархивируйте с отчетом о ходе работы:

public interface UnzipFile_Progress
{
    void Progress(int percent, String FileName);
}

// unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));
public static void UnzipFile(File zipFile, File targetDirectory, UnzipFile_Progress progress) throws IOException,
        FileNotFoundException
{
    long total_len = zipFile.length();
    long total_installed_len = 0;

    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
    try
    {
        ZipEntry ze;
        int count;
        byte[] buffer = new byte[1024];
        while ((ze = zis.getNextEntry()) != null)
        {
            if (progress != null)
            {
                total_installed_len += ze.getCompressedSize();
                String file_name = ze.getName();
                int percent = (int)(total_installed_len * 100 / total_len);
                progress.Progress(percent, file_name);
            }

            File file = new File(targetDirectory, ze.getName());
            File dir = ze.isDirectory() ? file : file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs())
                throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
            if (ze.isDirectory())
                continue;
            FileOutputStream fout = new FileOutputStream(file);
            try
            {
                while ((count = zis.read(buffer)) != -1)
                    fout.write(buffer, 0, count);
            } finally
            {
                fout.close();
            }

            // if time should be restored as well
            long time = ze.getTime();
            if (time > 0)
                file.setLastModified(time);
        }
    } finally
    {
        zis.close();
    }
}
person Behrouz.M    schedule 05.01.2015

public class MainActivity extends Activity {

private String LOG_TAG = MainActivity.class.getSimpleName();

private File zipFile;
private File destination;

private TextView status;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    status = (TextView) findViewById(R.id.main_status);
    status.setGravity(Gravity.CENTER);

    if ( initialize() ) {
        zipFile = new File(destination, "BlueBoxnew.zip");
        try {
            Unzipper.unzip(zipFile, destination);
            status.setText("Extracted to \n"+destination.getAbsolutePath());
        } catch (ZipException e) {
            Log.e(LOG_TAG, e.getMessage());
        } catch (IOException e) {
            Log.e(LOG_TAG, e.getMessage());
        }
    } else {
        status.setText("Unable to initialize sd card.");
    }
}

public boolean initialize() {
    boolean result = false;
     File sdCard = new File(Environment.getExternalStorageDirectory()+"/zip/");
    //File sdCard = Environment.getExternalStorageDirectory();
    if ( sdCard != null ) {
        destination = sdCard;
        if ( !destination.exists() ) {
            if ( destination.mkdir() ) {
                result = true;
            }
        } else {
            result = true;
        }
    }

    return result;
}

 }

-> Класс помощника (Unzipper.java)

    import java.io.File;
    import java.io.FileInputStream;
   import java.io.FileOutputStream;
    import java.io.IOException;
       import java.util.zip.ZipEntry;
    import java.util.zip.ZipException;
    import java.util.zip.ZipInputStream;
     import android.util.Log;

   public class Unzipper {

private static String LOG_TAG = Unzipper.class.getSimpleName();

public static void unzip(final File file, final File destination) throws ZipException, IOException {
    new Thread() {
        public void run() {
            long START_TIME = System.currentTimeMillis();
            long FINISH_TIME = 0;
            long ELAPSED_TIME = 0;
            try {
                ZipInputStream zin = new ZipInputStream(new FileInputStream(file));
                String workingDir = destination.getAbsolutePath()+"/";

                byte buffer[] = new byte[4096];
                int bytesRead;
                ZipEntry entry = null;
                while ((entry = zin.getNextEntry()) != null) {
                    if (entry.isDirectory()) {
                        File dir = new File(workingDir, entry.getName());
                        if (!dir.exists()) {
                            dir.mkdir();
                        }
                        Log.i(LOG_TAG, "[DIR] "+entry.getName());
                    } else {
                        FileOutputStream fos = new FileOutputStream(workingDir + entry.getName());
                        while ((bytesRead = zin.read(buffer)) != -1) {
                            fos.write(buffer, 0, bytesRead);
                        }
                        fos.close();
                        Log.i(LOG_TAG, "[FILE] "+entry.getName());
                    }
                }
                zin.close();

                FINISH_TIME = System.currentTimeMillis();
                ELAPSED_TIME = FINISH_TIME - START_TIME;
                Log.i(LOG_TAG, "COMPLETED in "+(ELAPSED_TIME/1000)+" seconds.");
            } catch (Exception e) {
                Log.e(LOG_TAG, "FAILED");
            }
        };
    }.start();
}

   }

-> макет xml (activity_main.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity" >

<TextView
    android:id="@+id/main_status"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/hello_world" />

</RelativeLayout>

-> разрешение в файле Menifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
person userDroid    schedule 03.09.2013

Вот ZipFileIterator (как java Iterator, но для zip-файлов):

package ch.epfl.bbp.io;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipFileIterator implements Iterator<File> {

    private byte[] buffer = new byte[1024];

    private FileInputStream is;
    private ZipInputStream zis;
    private ZipEntry ze;

    public ZipFileIterator(File file) throws FileNotFoundException {
    is = new FileInputStream(file);
    zis = new ZipInputStream(new BufferedInputStream(is));
    }

    @Override
    public boolean hasNext() {
    try {
        return (ze = zis.getNextEntry()) != null;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
    }

    @Override
    public File next() {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int count;

        String filename = ze.getName();
        File tmpFile = File.createTempFile(filename, "tmp");
        tmpFile.deleteOnExit();// TODO make it configurable
        FileOutputStream fout = new FileOutputStream(tmpFile);

        while ((count = zis.read(buffer)) != -1) {
        baos.write(buffer, 0, count);
        byte[] bytes = baos.toByteArray();
        fout.write(bytes);
        baos.reset();
        }
        fout.close();
        zis.closeEntry();

        return tmpFile;

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    }

    @Override
    public void remove() {
    throw new RuntimeException("not implemented");
    }

    public void close() {
    try {
        zis.close();
        is.close();
    } catch (IOException e) {// nope
    }
    }
}
person Renaud    schedule 04.06.2012
comment
как вы думаете, этот же код работает для распаковки или распаковки obb файлов расширения APK Expansion Files? - person LOG_TAG; 02.08.2012

Минимальный пример, который я использовал для распаковки определенного файла из моего zip-файла в папку кэша приложений. Затем я читаю файл манифеста другим методом.

private void unzipUpdateToCache() {
    ZipInputStream zipIs = new ZipInputStream(context.getResources().openRawResource(R.raw.update));
    ZipEntry ze = null;

    try {

        while ((ze = zipIs.getNextEntry()) != null) {
            if (ze.getName().equals("update/manifest.json")) {
                FileOutputStream fout = new FileOutputStream(context.getCacheDir().getAbsolutePath() + "/manifest.json");

                byte[] buffer = new byte[1024];
                int length = 0;

                while ((length = zipIs.read(buffer))>0) {
                    fout.write(buffer, 0, length);
                }
                zipIs .closeEntry();
                fout.close();
            }
        }
        zipIs .close();

    } catch (IOException e) {
        e.printStackTrace();
    }

}
person nilsi    schedule 13.03.2017

Я работаю с zip-файлами, которые класс Java ZipFile не может обрабатывать. Java 8, по-видимому, не может обрабатывать метод сжатия 12 (я полагаю, bzip2). Попробовав несколько методов, включая zip4j (который также не работает с этими конкретными файлами из-за другой проблемы), я добился успеха с Apache commons-compress, который поддерживает дополнительные методы сжатия, упомянутые здесь.

Обратите внимание, что приведенный ниже класс ZipFile не является классом из java.util.zip.

На самом деле это org.apache.commons.compress.archivers.zip.ZipFile, поэтому будьте осторожны с импортом.

try (ZipFile zipFile = new ZipFile(archiveFile)) {
    Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
    while (entries.hasMoreElements()) {
        ZipArchiveEntry entry = entries.nextElement();
        File entryDestination = new File(destination, entry.getName());
        if (entry.isDirectory()) {
            entryDestination.mkdirs();
        } else {
            entryDestination.getParentFile().mkdirs();
            try (InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) {
                IOUtils.copy(in, out);
            }
        }
    }
} catch (IOException ex) {
    log.debug("Error unzipping archive file: " + archiveFile, ex);
}

Для Gradle:

compile 'org.apache.commons:commons-compress:1.18'
person Manius    schedule 26.08.2018

Основываясь на ответе zapl, добавление try() вокруг Closeable автоматически закрывает потоки после использования.

public static void unzip(File zipFile, File targetDirectory) {
    try (FileInputStream fis = new FileInputStream(zipFile)) {
        try (BufferedInputStream bis = new BufferedInputStream(fis)) {
            try (ZipInputStream zis = new ZipInputStream(bis)) {
                ZipEntry ze;
                int count;
                byte[] buffer = new byte[Constant.DefaultBufferSize];
                while ((ze = zis.getNextEntry()) != null) {
                    File file = new File(targetDirectory, ze.getName());
                    File dir = ze.isDirectory() ? file : file.getParentFile();
                    if (!dir.isDirectory() && !dir.mkdirs())
                        throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
                    if (ze.isDirectory())
                        continue;
                    try (FileOutputStream fout = new FileOutputStream(file)) {
                        while ((count = zis.read(buffer)) != -1)
                            fout.write(buffer, 0, count);
                    }
                }
            }
        }
    } catch (Exception ex) {
        //handle exception
    }
}

Использование Constant.DefaultBufferSize (65536), полученного от C# .NET 4 Stream.CopyTo из ответа Джона Скита здесь: https://stackoverflow.com/a/411605/1876355

Я всегда просто вижу сообщения, использующие byte[1024] или byte[4096] буфер, никогда не знал, что он может быть намного больше, что улучшает производительность и все еще работает совершенно нормально.

Вот исходный код Stream: https://referencesource.microsoft.com/#mscorlib/system/io/stream.cs

//We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
// The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
// improvement in Copy performance.

private const int _DefaultCopyBufferSize = 81920;

Однако я снова набрал 65536, что также кратно 4096, на всякий случай.

person Pierre    schedule 31.10.2019
comment
Это лучшее решение в этой теме. Кроме того, я бы также использовал BufferedOutputStream в стеке с FileOutputStream. - person MarkoR; 25.12.2019

ZIP-файл, защищенный паролем

если вы хотите сжать файлы с паролем, вы можете взглянуть на эту библиотеку, которая может архивировать файлы с паролем легко:

Почтовый индекс:

ZipArchive zipArchive = new ZipArchive();
zipArchive.zip(targetPath,destinationPath,password);

Разархивировать:

ZipArchive zipArchive = new ZipArchive();
zipArchive.unzip(targetPath,destinationPath,password);

Rar:

RarArchive rarArchive = new RarArchive();
rarArchive.extractArchive(file archive, file destination);

Документация этой библиотеки достаточно хороша, я просто добавил оттуда несколько примеров. Это совершенно бесплатно и написано специально для Android.

person Milad Faridnia    schedule 07.11.2017