Как программно разархивировать файлы в 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-файлами, которые не содержат каталогов.
- если 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()