在 GZIP 解压过程中设置 ProgressBar maxValue 和 publishProgress 值

Posted

技术标签:

【中文标题】在 GZIP 解压过程中设置 ProgressBar maxValue 和 publishProgress 值【英文标题】:Set ProgressBar maxValue and publishProgress values during GZIP decompressing 【发布时间】:2017-04-01 17:18:27 【问题描述】:

我有一个 AsyncTask 正在执行解压缩 GZIP 文件的工作。我刚刚了解到我可以发布 AsyncTasks 的进度,并且成功地设法让它与我之前创建的其他 AsyncTasks 一起工作。我知道要做到这一点,需要 2 个重要值,最大值和当前进度值。

我的问题是我不确定如何从输入流中检索这些值。我当前的 AsyncTask 如下所示:

package com.wizzkidd.myapp.asynctasks;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;

public class DecompressGzipAsync extends AsyncTask<String, Integer, Boolean> 

    ProgressBar progressBar;
    private Context _context;
    private View _view;
    private String _compressedFilePath;
    private String _uncompressedFilePath;

    public DecompressGzipAsync(Context context, View view, String compressedFilePath) 
        this._context = context;
        this._view = view;
        this._compressedFilePath = compressedFilePath;
        this._uncompressedFilePath = compressedFilePath.substring(0, compressedFilePath.lastIndexOf(".")); //path + filename without gz extension
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
    

    @Override
    protected Boolean doInBackground(String... strings) 
        Boolean isSuccess = false;
        byte[] buffer = new byte[1024];
        try 
            GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(_compressedFilePath));
            FileOutputStream out = new FileOutputStream(_uncompressedFilePath);
            //FIXME: I think I need the file size here?
            //progressBar.setMax(???);
            int len;
            while ((len = gzis.read(buffer)) > 0) 
                out.write(buffer, 0, len);
                //FIXME: I'm not sure what incrementing value can I put in here?
                //publishProgress(???);
            
            gzis.close();
            out.close();
            isSuccess = true;
         catch (IOException ex) 
            ex.printStackTrace();
        
        return isSuccess;
    

    @Override
    protected void onProgressUpdate(Integer... values) 
        super.onProgressUpdate(values);
        int currentValue = values[0];
        int maxValue = progressBar.getMax();
        Log.v("TAG", "Decompressing Progress... currentValue: " + currentValue + " | maxValue: " + maxValue);
    

    @Override
    protected void onPostExecute(Boolean result) 
        super.onPostExecute(result);
        if (result) 
            Log.v("TAG", "Decompressing - Completed");
         else 
            Log.v("TAG", "Decompressing - Failed");
        
    

我在我的代码中评论了我认为我需要找到值的地方,但在这里需要一些帮助。任何帮助表示赞赏。

【问题讨论】:

【参考方案1】:

根据this post,文件的最后四个字节包含未压缩的文件大小(这意味着限制为 4GB)。

所以这应该有效:

    @Override
    protected Boolean doInBackground(String... strings) 
        Boolean isSuccess = false;
        byte[] buffer = new byte[1024];
        try 
            RandomAccessFile raf = new RandomAccessFile(new File(_compressedFilePath), "r");
            raf.seek(raf.length() - 4);
            int b4 = raf.read();
            int b3 = raf.read();
            int b2 = raf.read();
            int b1 = raf.read();
            int uncompressedSize = ((0xFF & b1) << 24) | ((0xFF & b2) << 16) |
                    ((0xFF & b3) << 8) | (0xFF & b4);
            raf.close();

            GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(_compressedFilePath));
            FileOutputStream out = new FileOutputStream(_uncompressedFilePath);
            int count = 0;
            int len;
            while ((len = gzis.read(buffer)) > 0) 
                out.write(buffer, 0, len);
                count += len;
                publishProgress(count, uncompressedSize);
            
            gzis.close();
            out.close();
            isSuccess = true;
         catch (IOException ex) 
            Log.e("DecompressGzipAsync", "error unzipping file", ex);
        
        return isSuccess;
    

    @Override
    protected void onProgressUpdate(Integer... values) 
        super.onProgressUpdate(values);
        int count = values[0];
        int uncompressedSize = values[1];
        int maxValue = progressBar.getMax();
        int progress = (int) ((float) count / (float) uncompressedSize * maxValue);
        if (progress > maxValue) progress = maxValue;  // sanity check
        progressBar.setProgress(progress);
        Log.v("DecompressGzipAsync", "Decompressing Progress... currentValue: " + progress + " | maxValue: " + maxValue);
    

【讨论】:

谢谢@kris,您不仅提供了答案,而且还进一步将答案实现到我现有的代码中。现在,如果那不是勺子喂食,我不知道是什么。非常感谢! 当它复制/粘贴一堆代码并更改几行时,我很乐意这样做。 :)

以上是关于在 GZIP 解压过程中设置 ProgressBar maxValue 和 publishProgress 值的主要内容,如果未能解决你的问题,请参考以下文章

前端优化(webpack, js, html)

如何在Gitlab中设置HTTP缓存标头?

如何在存储过程中设置日期时间可选参数?

Unity LZMA GZIP 压缩解压文件 和 打包文件夹 (支持进度回调)

在 SQL 中插入一行并在存储过程中设置变量?

在开发过程中设置管理员角色