【问题标题】:Phone get hanged while unzipping a file in android在android中解压缩文件时手机被挂起
【发布时间】:2023-07-14 12:06:01
【问题描述】:

我正在尝试在 android 手机中解压缩一个 .zip 文件。下面的代码工作正常。

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

}

当我使用参数调用此方法时,它会成功解压缩文件,但问题是文件大小为 55MB,并且在调用此方法之前应用程序运行良好,但是当我调用此方法时,该应用程序大约需要 8-13 秒需要解压缩应用程序卡住的文件,没有任何工作,但在成功解压缩文件后,应用程序再次运行良好,所以请帮助我,以便应用程序在解压缩文件期间工作。 我也尝试在

中执行该方法
runOnUiThread(new Runnable() {

});

但没有成功。

【问题讨论】:

  • 您的代码遇到了 CERT 在this advisory 中引用的解压缩问题。除了使用下面第一个答案中看到的后台线程之外,请考虑进行验证以确保您没有在 targetDirectory 之外解压缩文件,并且更不受 zip 炸弹和类似攻击的影响。我的 CWAC-Security 库有一个 ZipUtils 类和一个 unzip() 方法来解决这些攻击:github.com/commonsguy/cwac-security/#usage-ziputils

标签: android multithreading performance file unzip


【解决方案1】:

如果应用程序冻结,通常是因为您在主/UI 线程上进行了太多计算(请注意,runOnUiThread() 正是这样做的)。为避免这种情况,您必须在另一个线程或 AsyncTask 中调用您的方法。

快速而肮脏的解决方法是使用普通线程:

new Thread(new Runnable() {
    public void run() {
        unzip(zipFile, targetDirectory);
    }
}).start();

或者使用 AsyncTask:

new AsyncTask<File, Void, Void>() {
     protected Void doInBackground(File... files) {
         unzip(files[0], files[1]);
         return null;
     }

     protected void onPostExecute(Void result) {
         // we're finished
     }
}.execute(zipFile, targetDirectory);

【讨论】:

  • 非常感谢您的帮助。我已经使用了“AsyncTask”并且它工作得很好但是遇到了一个新问题,如果我在不使用“AsyncTask”的情况下运行应用程序,在应用程序退出“System.Exit(0)”时我的应用程序成功关闭但是当我使用“AsyncTask”时”,在使用“System.Exit(0)”退出应用程序后,应用程序再次重新启动,并且在“AsyncTask”的“doInBackground”中写入了相同的方法。所以请帮助我如何解决这个问题,以便应用程序完全关闭。