Что-то не так с моим кодом?Почему скорость сжатия и распаковки ниже, чем у другого приложения? - PullRequest
2 голосов
/ 26 апреля 2019

Я создаю приложение сжатия и распаковки, которое использует метод сжатия xz. Но сжатие и распаковка медленнее по сравнению с другим приложением, которое также использует тот же метод сжатия. Например, я попытался распаковать файл 15 МБ в файл 40 МБ, и мой код занимает около 18 секунд, в то время как в другом приложении это занимает всего около 4 секунд.

Я использую XZInputStream из XZ для Java и TarArchiveInputStream из Apache Common Compress

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

1 Ответ

0 голосов
/ 26 апреля 2019

Я не знаю о производительности библиотеки, которую вы используете.Однако я могу просто оставить свои предложения здесь, которые могут помочь вам улучшить производительность.

Похоже, вы блокируете поток пользовательского интерфейса , используя эту большую операцию внутри цикла while.Я хотел бы предложить вам создать AsyncTask, а затем поместить туда код в функции doInBackground, которая не будет блокировать поток пользовательского интерфейса, и об операции позаботится с фоновым потоком.

Кстати, об использовании фонового потока.Вы можете также рассмотреть возможность использования нескольких потоков для распаковки вашего файла.Я не уверен в том, как это можно сделать, однако я мог бы предложить идею, подобную следующей.

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 занимает много времени, и, следовательно, вы можете рассмотреть вопрос об установкеBufferedInputStream в середине, как показано ниже.

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