首页 > 解决方案 > 我的代码有什么问题吗?为什么压缩和解压缩速度比其他应用程序慢?

问题描述

我正在创建使用 xz 压缩方法的压缩和解压缩应用程序。但是与使用相同压缩方法的另一个应用程序相比,压缩和解压缩速度较慢。例如,我尝试将 15mb 文件解压缩为 40mb 文件,我的代码大约需要 18 秒,而在另一个应用程序上只需要大约 4 秒。

我正在使用来自XZ for Java的 XZInputStream 和来自Apache Common Compress的 TarArchiveInputStream

public static void decompress(File file, String targetPath) {
    try {
        File outputFile = new File(targetPath);
        FileInputStream fileInputStream = new FileInputStream(file);
        XZInputStream xzInputStream = new XZInputStream(fileInputStream);
        TarArchiveInputStream tarInputStream = new TarArchiveInputStream(xzInputStream);
        TarArchiveEntry entry;
        while ((entry = tarInputStream.getNextTarEntry()) != null) {
            if (entry.isDirectory()) {
                continue;
            }
            File curFile = new File(outputFile, entry.getName());
            File parent = curFile.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
            IOUtils.copy(tarInputStream, new FileOutputStream(curFile));
        }
    } catch (FileNotFoundException e) {
        Log.e("Exception", Log.getStackTraceString(e));
    } catch (IOException e) {
        Log.e("Exception", Log.getStackTraceString(e));
    }
}

标签: javaandroidperformancecompressionxz

解决方案


我不知道您正在使用的库的性能。但是,我可以在这里放弃我的建议,这可能会帮助您提高性能。

看起来您正在使用循环中的这个大操作阻塞 UI 线程。while我建议您创建一个AsyncTask然后将代码放在doInBackground不会阻塞 UI 线程的函数中,并且该操作将由后台线程处理。

说到使用后台线程。你也可以考虑使用多线程来解压你的文件。我不确定如何做到这一点,但是,我可能会提出如下的想法。

while ((entry = tarInputStream.getNextTarEntry()) != null) {
    if (entry.isDirectory()) continue;

    File curFile = new File(outputFile, entry.getName());
    File parent = curFile.getParentFile();
    if (!parent.exists()) {
        parent.mkdirs();
    }

    // Create a thread for each of these operations and do it in background. 
    // Thus you can take the advantage of using multiple threads to process your operations faster
    // Instead of passing the whole tarInputStream, just pass the entry and check if that works.
    IOUtils.copy(entry, new FileOutputStream(curFile));
}

希望有帮助!

更新

我认为从 复制InputStream需要很多时间,因此您可以考虑将 aBufferedInputStream放在这些中间,如下所示。

FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bin = new BufferedInputStream(fileInputStream); 
XZInputStream xzInputStream = new XZInputStream(bin);

推荐阅读