답변:
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;
}
ze
디렉토리 인 경우 "파일 전용"조작을 건너 뛰어야하므로 . 이러한 작업을 수행하려고하면 예외가 발생합니다.
Vasily Sochinsky의 답변을 약간 수정하고 약간 수정했습니다.
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
-이것은 어디에나있을 수있는 정적 유틸리티 방법입니다.File
때문에 매개 변수 String
파일 /와 zip 파일이 이전에 추출 될 위치를 하나 지정하지 수 : 있습니다. 또한 path + filename
연결> https://stackoverflow.com/a/412495/995891throws
- 늦게 잡기 때문에 -관심이 없다면 시도 잡기를 추가하십시오.mkdirs()
이 중요합니다.finally
리소스를 사용하여 리소스 누수를 방지합니다.그래서
unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));
원본과 동등한 작업을 수행해야합니다
unpackZip("/sdcard/", "pictures.zip")
UTF8 format
합니다. 그래서 아파치의 lib 를 사용하는 대신 이 코드 를 사용했습니다 commons-compress
.
이것은 내가 사용하는 압축 해제 방법입니다.
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 클래스 는 살펴 봐야 할 것입니다. ZipInputStream에서 ZipEntry를 읽고 파일 시스템 / 폴더에 덤프하십시오. zip 파일 로 압축하려면 비슷한 예를 확인하십시오 .
코 틀린 방식
//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()
UPDATE 2016은 다음 클래스를 사용합니다
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();
권한
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@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();
}
}
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"/>
다음은 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
}
}
}
최소한의 예는 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();
}
}
Java의 ZipFile 클래스가 처리 할 수없는 zip 파일로 작업하고 있습니다. 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'
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
}
}
Jon Skeet의 답변 에서 Stream.CopyTo 에서 얻은 Constant.DefaultBufferSize
( 65536
) 사용 :
https://stackoverflow.com/a/411605/1876355C# .NET 4
나는 항상 그냥 사용 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
를 사용했습니다.
비밀번호로 보호 된 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 용으로 특별히 작성되었습니다.