在Android中以编程方式解压文件

7
我正在下载一个zip文件并将其保存在我的安卓设备的特定文件夹中。由于文件被压缩,我的应用程序无法访问该文件夹。我想在从服务器下载后解压缩文件夹并保存到指定文件夹中。
这是我的代码:
public void DownloadDatabase(String DownloadUrl, String fileName) {
    try {
        File root = android.os.Environment.getExternalStorageDirectory();
        File dir = new File(root.getAbsolutePath() + "/timy/databases");
        if(dir.exists() == false){
             dir.mkdirs();  
        }

        URL url = new URL("http://myexample.com/android/timy.zip");
        File file = new File(dir,fileName);

        long startTime = System.currentTimeMillis();
        Log.d("DownloadManager" , "download url:" +url);
        Log.d("DownloadManager" , "download file name:" + fileName);

        URLConnection uconn = url.openConnection();
        uconn.setConnectTimeout(TIMEOUT_SOCKET);

        InputStream is = uconn.getInputStream();

        ZipInputStream zipinstream = new ZipInputStream(new BufferedInputStream(is));
        ZipEntry zipEntry;

        while((zipEntry = zipinstream.getNextEntry()) != null){
            String zipEntryName = zipEntry.getName();
            File file1 = new File(file + zipEntryName);
            if(file1.exists()){

            }else{
                if(zipEntry.isDirectory()){
                    file1.mkdirs();
                }
            }
        }

        BufferedInputStream bufferinstream = new BufferedInputStream(is);

        ByteArrayBuffer baf = new ByteArrayBuffer(5000);
        int current = 0;
        while((current = bufferinstream.read()) != -1){
            baf.append((byte) current);
        }

        FileOutputStream fos = new FileOutputStream( file);
        fos.write(baf.toByteArray());
        fos.flush();
        fos.close();
        Log.d("DownloadManager" , "download ready in" + ((System.currentTimeMillis() - startTime)/1000) + "sec");
    }
    catch(IOException e) {
        Log.d("DownloadManager" , "Error:" + e);
        e.printStackTrace();
    }

}

我的logcat显示出现错误。只有文件夹在我的设备上创建,没有任何文件被下载并解压缩。如果不使用inputZipStream方法,则我的压缩文件夹会下载并保存在sdcard中。但是当我想要解压缩它时,却没有发生任何事情。

3个回答

23

本文介绍如何使用内置的Java API编写实用程序类,从压缩的zip归档文件中提取文件和目录。

java.util.zip包提供以下类来从ZIP存档文件中提取文件和目录:

ZipInputStream:这是主要的类,可用于读取zip文件并提取归档文件中的文件和目录(条目)。以下是此类的一些重要用法: - 通过其构造函数ZipInputStream(FileInputStream)读取zip文件 - 通过方法getNextEntry()读取文件和目录的条目 - 通过方法read(byte)读取当前条目的二进制数据 - 通过方法closeEntry()关闭当前条目 - 通过方法close()关闭zip文件

ZipEntry:此类表示zip文件中的条目。每个文件或目录都表示为ZipEntry对象。它的方法getName()返回一个字符串,表示文件/目录的路径。路径的格式如下: folder_1/subfolder_1/subfolder_2/…/subfolder_n/file.ext

根据ZipEntry的路径,在提取zip文件时重新创建目录结构。

下面的类用于解压下载的zip文件并提取文件并将其存储在所需位置。

  public class UnzipUtil
  {
     private String zipFile;
     private String location;

  public UnzipUtil(String zipFile, String location)
  {
     this.zipFile = zipFile;
     this.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());     

 byte[] buffer = new byte[8192];
 int len;
 while ((len = zin.read(buffer)) != -1)
 {
  fout.write(buffer, 0, len);
 }
 fout.close();

 zin.closeEntry();

}

    }
      zin.close();
    }
     catch(Exception e)
     {
          Log.e("Decompress", "unzip", e);
     }

  }

   private void dirChecker(String dir)
   {
         File f = new File(location + dir);
         if(!f.isDirectory())
          {
            f.mkdirs();
          }
         }
    }

MainActivity类:

       public class MainActivity extends Activity
        {
        private ProgressDialog mProgressDialog;

        String Url="http://hasmukh/hb.zip";
        String unzipLocation = Environment.getExternalStorageDirectory() + "/unzipFolder/";
        String StorezipFileLocation =Environment.getExternalStorageDirectory() +                       "/DownloadedZip"; 
       String DirectoryName=Environment.getExternalStorageDirectory() + "/unzipFolder/files/";

       @Override
       protected void onCreate(Bundle savedInstanceState)
       {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

           DownloadZipfile mew = new DownloadZipfile();
            mew.execute(url);

        }

        //-This is method is used for Download Zip file from server and store in Desire location.
        class DownloadZipfile extends AsyncTask<String, String, String>
         {
         String result ="";
          @Override
          protected void onPreExecute()
          {
            super.onPreExecute();
            mProgressDialog = new ProgressDialog(MainActivity.this);
            mProgressDialog.setMessage("Downloading...");
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setCancelable(false);
            mProgressDialog.show();
            }

             @Override
             protected String doInBackground(String... aurl)
             {
              int count;

                    try
          {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
InputStream input = new BufferedInputStream(url.openStream());

OutputStream output = new FileOutputStream(StorezipFileLocation);

byte data[] = new byte[1024];
long total = 0;

while ((count = input.read(data)) != -1)
{
 total += count;
 publishProgress(""+(int)((total*100)/lenghtOfFile));
 output.write(data, 0, count);
}
output.close();
input.close();
result = "true";

         } catch (Exception e) {

         result = "false";
         }
        return null;

       }
        protected void onProgressUpdate(String... progress)
        {
        Log.d("ANDRO_ASYNC",progress[0]);
        mProgressDialog.setProgress(Integer.parseInt(progress[0]));
        }

         @Override
         protected void onPostExecute(String unused)
         {
               mProgressDialog.dismiss();
               if(result.equalsIgnoreCase("true"))
         {
          try
             {
                unzip();
                   } catch (IOException e)
                   {
                 // TODO Auto-generated catch block
              e.printStackTrace();
              }
                 }
                     else
                   {

                   }
                       }
               }
          //This is the method for unzip file which is store your location. And unzip folder will                 store as per your desire location.



             public void unzip() throws IOException 
            {
            mProgressDialog = new ProgressDialog(MainActivity.this);
            mProgressDialog.setMessage("Please Wait...");
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mProgressDialog.setCancelable(false);
            mProgressDialog.show();
            new UnZipTask().execute(StorezipFileLocation, DirectoryName);
              }


          private class UnZipTask extends AsyncTask<String, Void, Boolean> 
          {
          @SuppressWarnings("rawtypes")
          @Override
          protected Boolean doInBackground(String... params) 
          {
             String filePath = params[0];
             String destinationPath = params[1];

               File archive = new File(filePath);
                try 
                 {
                 ZipFile zipfile = new ZipFile(archive);
                 for (Enumeration e = zipfile.entries(); e.hasMoreElements();) 
                 {
                         ZipEntry entry = (ZipEntry) e.nextElement();
                         unzipEntry(zipfile, entry, destinationPath);
                    }


         UnzipUtil d = new UnzipUtil(StorezipFileLocation, DirectoryName); 
         d.unzip();

            } 
    catch (Exception e) 
         {
           return false;
         }

          return true;
       }

           @Override
           protected void onPostExecute(Boolean result) 
           {
                mProgressDialog.dismiss(); 

             }


            private void unzipEntry(ZipFile zipfile, ZipEntry entry,String outputDir) throws IOException 
         {

                  if (entry.isDirectory()) 
        {
                createDir(new File(outputDir, entry.getName()));
                return;
          }

           File outputFile = new File(outputDir, entry.getName());
           if (!outputFile.getParentFile().exists())
           {
              createDir(outputFile.getParentFile());
           }

           // Log.v("", "Extracting: " + entry);
          BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
          BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));

       try 
        {

         }
       finally 
         {
              outputStream.flush();
              outputStream.close();
              inputStream.close();
          }
           }

             private void createDir(File dir) 
             {
                if (dir.exists()) 
              {
                   return;
                  }
                    if (!dir.mkdirs()) 
                      {
                        throw new RuntimeException("Can not create dir " + dir);
               }
               }}
                 }

            Note: Do not forgot to add below  permission in android Manifest.xml file.

          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>
      <uses-permission android:name="android.permission.INTERNET" />

阅读更多


@RathaKrishna,我遇到了反斜杠的问题。我得到的文件路径是sdcard/temp/765\765.json,有没有什么方法可以解决? - Ando Masahashi
@Ando filepath = filepath.replace("", "/"); @Ando 文件路径 = 文件路径.replace("", "/"); - Matthew Carpenter
非常好用。非常感谢 :) - Anjana Silva
一个小更新,最新的安卓系统中,文件权限已经改变,因此文件位置应该被更改,例如媒体位置在这里 https://developer.android.com/training/data-storage/manage-all-files - Y00

5
解压函数
public void unzip(String _zipFile, String _targetLocation) {

    //create target location folder if not exist 
    dirChecker(_targetLocatioan); 

    try { 
        FileInputStream fin = new FileInputStream(_zipFile);
        ZipInputStream zin = new ZipInputStream(fin);
        ZipEntry ze = null;
        while ((ze = zin.getNextEntry()) != null) {

            //create dir if required while unzipping 
            if (ze.isDirectory()) {
                dirChecker(ze.getName());
            } else { 
                FileOutputStream fout = new FileOutputStream(_targetLocation + ze.getName());
                for (int c = zin.read(); c != -1; c = zin.read()) {
                    fout.write(c);
                } 

                zin.closeEntry();
                fout.close();
            } 

        } 
        zin.close();
    } catch (Exception e) {
        System.out.println(e);
    } 
} 

初始化

ZipManager zipManager = new ZipManager();

zipManager.unzip(inputPath + inputFile, outputPath);

2
太棒了,简单易懂!只需要两个小调整:加入缓冲区并修改输入/输出循环。这样程序就会飞快地运行。先定义一个byte数组作为缓冲区,比如byte[] buff = new byte[4096],然后使用zin.read(buff)和fout.write(buff, 0, 4096)来读取和写入数据。最后,在while循环中使用spin on a while (len = zin.read(buff) >0)来不断读取数据。 - MarkDubya

-1

对于安卓系统,有一个第三方库可以免费使用。
这个库会自动下载你的文件并在你想要的位置解压缩它。
你可以在这里查看这个库。
安卓解压库


1
仅限于JAR文件。请勿误导。 - Ranjithkumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接