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

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

Версия пено оптимизирована. Наблюдается увеличение производительности.

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) { // zapis do souboru 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); // cteni zipu a zapis 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; } 

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

 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 – потому что поймать поздно – добавьте попытку поймать, если действительно не заинтересованы в них.
  • фактически гарантирует, что требуемые каталоги существуют во всех случаях. Не каждый почтовый индекс содержит все необходимые записи в каталоге до ввода файлов. Это имело 2 потенциальных ошибки:
    • если zip содержит пустой каталог, а вместо результирующего каталога есть существующий файл, это игнорировалось. Возвращаемое значение mkdirs() важно.
    • может привести к сбою в zip-файлах, которые не содержат каталогов.
  • увеличенный размер буфера записи, это должно немного улучшить производительность. Хранение обычно происходит в 4-х блоках, а запись в небольших кусках обычно медленнее, чем необходимо.
  • использует магию, finally для предотвращения утечек ресурсов.

Так

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

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

 unpackZip("/sdcard/", "pictures.zip") 

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

 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; } 

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

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

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

Согласно ответу @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(); } } 

UPDATE 2016 использует следующий class

  package com.example.zip; 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(); 

права доступа

    
 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 layout (activity_main.xml):

    

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

  

Путь Котлин

 //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) } } } } } - //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() 

Вот 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 { 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 } } } 

Минимальный пример. Я использовал, чтобы разархивировать определенный файл из моего 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(); } } 

Защищенный паролем файл Zip

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

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

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

Распакуйте:

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

Рар:

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

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

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

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

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

 try (ZipFile zipFile = new ZipFile(archiveFile)) { Enumeration 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' 
  • Как вы используете Intent.FLAG_ACTIVITY_CLEAR_TOP, чтобы очистить стек активности?
  • ListView OnItemClickListener не отвечает?
  • как разобрать JSONArray в android
  • Отсутствует оператор return для оператора if / else
  • Что такое пул строк в Java?
  • Насколько велика ссылка на объект в Java и какая именно информация содержится в ней?
  • Что именно влияет на URLConnection.setDoOutput ()?
  • Глобальные переменные в Java
  • Какова наилучшая практика для округления поплавка до 2 десятичных знаков?
  • Как вы получаете выбранное значение Spinner?
  • Android - Изменить тему приложения onClick
  • Давайте будем гением компьютера.