Android

How to unzip files programmatically in Android?

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

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

Переведено автоматически
Ответ 1

Версия peno была немного оптимизирована. Увеличение производительности заметно.

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;
}
Ответ 2

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

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://javalang.ru/a/412495/995891

  • throws - потому что ловить поздно - добавьте try catch, если они действительно не интересны.

  • на самом деле гарантирует, что требуемые каталоги существуют во всех случаях. Не каждый zip-файл содержит все необходимые записи каталогов перед записями файлов. В нем было 2 потенциальных ошибки.:

    • если zip содержит пустой каталог, а вместо результирующего каталога есть существующий файл, это было проигнорировано. Важно возвращаемое значение mkdirs().

    • может произойти сбой при работе с zip-файлами, которые не содержат каталогов.


  • увеличенный размер буфера записи должен немного повысить производительность. Хранилище обычно состоит из блоков 4k, а запись меньшими порциями обычно выполняется медленнее, чем необходимо.

  • использует магию finally для предотвращения утечки ресурсов.

Итак

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

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

unpackZip("/sdcard/", "pictures.zip")
Ответ 3

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

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;
}
Ответ 4

Способ Kotlin

//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()
java android