[java] 안드로이드에서 프로그래밍 방식으로 파일을 압축 해제하는 방법은 무엇입니까?

주어진 .zip 파일에서 몇 개의 파일을 압축 해제하고 압축 파일의 형식에 따라 별도의 파일을 제공하는 작은 코드 스 니펫이 필요합니다. 당신의 지식을 게시하고 도와주세요.



답변

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


답변

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/995891
  • throws늦게 잡기 때문에 -관심이 없다면 시도 잡기를 추가하십시오.
  • 실제로 필요한 디렉토리가 모든 경우에 존재하는지 확인합니다. 모든 zip에 파일 항목 이전에 필요한 모든 디렉토리 항목이있는 것은 아닙니다. 여기에는 2 가지 잠재적 버그가있었습니다.
    • zip에 빈 디렉토리가 있고 결과 디렉토리 대신 기존 파일이 있으면 무시됩니다. 의 반환 값 mkdirs()이 중요합니다.
    • 디렉토리가없는 zip 파일에서 충돌이 발생할 수 있습니다.
  • 쓰기 버퍼 크기가 증가하면 성능이 약간 향상됩니다. 스토리지는 일반적으로 4k 블록으로 이루어지며 작은 청크로 쓰기는 보통 필요한 것보다 느립니다.
  • 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 클래스 는 살펴 봐야 할 것입니다. 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()


답변

이미 여기에있는 답변이 잘 작동하는 동안 나는 그들이 기대했던 것보다 약간 느리다는 것을 알았습니다. 대신 zip4j을 사용 했는데 속도 때문에 최고의 솔루션이라고 생각합니다. 또한 압축 량에 대해 다른 옵션을 사용할 수 있었으므로 유용하다고 생각했습니다.


답변

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" />