12

我有一个看起来很简单的问题,但我似乎无法让它正常工作。

我的“资产”文件夹中有一个需要解压缩的 zip 文件,并且我有一个ProgessBar要向用户显示进度的文件。

我一切正常,但我想将ProgessBar最大值设置为 zip 文件中的文件数。此文件夹中的文件数量有时会发生变化,因此我希望它ProgessBar与 zip 中包含的文件数量相关。

我正在使用ZipInputStream-API 但似乎没有办法获取 zip 文件中的文件数。我能想到的唯一方法是这样做:

   ZipInputStream zin = new ZipInputStream(getAssets().open(
                                "myFile.zip"));
   int numFiles = 0;
   int increment = 0;
   while (zin.getNextEntry() != null) {
     numFiles++;
    }

    ZipEntry ze = null;
    //Set the Max..value here..
    progessBar.setMax(numFiles);                
    while ((ze = zin.getNextEntry()) != null) {
       increment++;
       progessBar.setProgress(increment);
    }

这行得通,但是有两个 while 循环似乎有点多余,它们基本上在做同样的事情。

我知道有一个ZipFile-API 有一个size()- 方法,但它需要文件的路径,并且由于我的文件位于“资产”文件夹中,我很确定从该目录读取的唯一方法是通过流式传输。

我有办法做到这一点吗?

4

4 回答 4

9

感谢您的回答。我最终使用AssetFileDescriptorAPI 获取 zip 文件的文件大小并将其设置为ProgessBar.setMax()值。然后,当我遍历 zip 内容时,我使用每个条目的文件大小来增加进度。这可行,但我唯一担心的是AssetFileDescriptor.getLength()值和ZipEntry.getSize()值都返回一个long值,所以我被迫将它们转换为整数,然后才能设置最大值和/或递增,ProgessBar所以我可能会超载一个导致异常的整数值,但这不太可能,因为我预计我的文件大小不会超过整数的最大容纳容量。

ZipInputStream zin = new ZipInputStream(getAssets().open(
                            "myFile.zip"));
ZipEntry ze = null;
AssetFileDescriptor mydisc = getAssets().openFd("myFile.zip");
//Size of the zip package
long size = mydisc.getLength();
long increment = 0;
dialog.setMax((int) size);
while ((ze = zin.getNextEntry()) != null) {
     increment += (int) ze.getSize();
     progessBar.setProgess((int)increment);
     //do more stuff..
}

不是最好的解决方案,但它有效。

我知道ZipFileAPI,但它需要传入一个字符串,但我不确定该目录的路径是什么或如何获取它?

于 2011-07-25T16:35:46.527 回答
5

使用API ,ZipFile有一个size方法可以返回ZipEntries. ZipFile您可以从资产文件夹中读取。

例子:

int zipEntriesCount(String path) throws IOException {

     ZipFile zf= new ZipFile(path);
     return zf.size();
}
于 2011-07-23T02:58:01.973 回答
4

您的基本问题似乎是progressBar.setMax()在开始读取文件之前必须做的事情,并且您正在根据文件数设置最大值。

您是否考虑过progressBar.setMax(zin.getSize())在调用时跟踪您写入的字节progressBar.setProgress()数,而不是读取的文件数?这应该可以解决您的问题,并将为您(恕我直言)提供更准确的进度条。

于 2011-07-23T02:40:23.870 回答
1

这是我基于@davorb 想法的解决方案,它根据文件大小而不是 zip 文件的内容显示进度。

import android.content.Context;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipUtility {
    private final String TAG = "Decompress";
    private ZipExtractionCallback zipExtractionCallback;

    public ZipUtility(ZipExtractionCallback zipExtractionCallback) {
        this.zipExtractionCallback = zipExtractionCallback;
    }
//
//    private void unzipFromAssets(Context context, String zipFile, String destination) {
//        try {
//            if (destination == null || destination.length() == 0)
//                destination = context.getFilesDir().getAbsolutePath();
//            new File(destination).delete();
//            InputStream stream = context.getAssets().open(zipFile);
//            unzip(stream, destination);
////            SharedPreferenceHelper.Write(context,
////                    SharedPreferenceConst.SharedPreferenceName,
////                    SharedPreferenceConst.MapExtracted,
////                    "1");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }

    private boolean deleteDirectory(String file) /*throws IOException, InterruptedException */ {

        try {
            if (new File(file).exists()) {
                String deleteCommand = "rm -rf " + file/*.getAbsolutePath()*/;
                Runtime runtime = Runtime.getRuntime();
                Process process = runtime.exec(deleteCommand);
                process.waitFor();
                return true;
            }
        } catch (Exception ignore) {
        }

        return false;
    }

    public void unzipFromPath(Context context, String zipFilePath, String destination) {

        try {
            if (destination == null || destination.length() == 0)
                destination = context.getFilesDir().getAbsolutePath();
            zipExtractionCallback.progress(0, "حذف فایل های قدیمی...");
            deleteDirectory(destination + "html");
            unzip(zipFilePath, destination);
            zipExtractionCallback.progress(0, "حذف فایل اضافی...");
            deleteDirectory(zipFilePath);
        } catch (IOException e) {
            zipExtractionCallback.error("خطا هنگام عملیات استخراج : " + e.getMessage());
            e.printStackTrace();
        }
        zipExtractionCallback.finish();
    }
//
//    public static void unzip(String zipFile, String location) {
//        try {
//            FileInputStream fin = new FileInputStream(zipFile);
//            unzip(fin, location);
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//
//    }

    private void unzip(String zipFilePath, String destination) throws IOException {
        long size = new File(zipFilePath).length();
        long decompressedSize = 0;
        InputStream stream = new FileInputStream(new File(zipFilePath));
        dirChecker(destination, "");
//        int entries = 0;
        int total = 0;
        ZipInputStream zin = new ZipInputStream(stream);

//        while ((zin.getNextEntry()) != null) {
//            if (entries % 100 == 0)
//                zipExtractionCallback.progress(0, "در حال خواندن محتویات:" + entries + " فایل");
//            entries++;
//        }
        zin.close();
        stream = new FileInputStream(new File(zipFilePath));
        int p = 0;
        long totalBytes = 0;
        int BUFFER_SIZE = 1024 * 10;
        byte[] buffer = new byte[BUFFER_SIZE];
        try {
            zin = new ZipInputStream(stream);
            ZipEntry ze = null;
            while ((ze = zin.getNextEntry()) != null) {
                decompressedSize += ze.getSize();
                //Log.v(TAG, "Unzipping " + ze.getName());
                if (ze.isDirectory()) {
                    dirChecker(destination, ze.getName());
                } else {
                    File f = new File(destination, ze.getName());
                    if (!f.exists()) {
                        boolean success = f.createNewFile();
                        if (!success) {
                            //Log.w(TAG, "Failed to create file " + f.getName());
                            continue;
                        }
                        FileOutputStream fout = new FileOutputStream(f);
                        //BufferedOutputStream out = new BufferedOutputStream(fout);
                        int count;
                        while ((count = zin.read(buffer)) != -1) {
                            fout.write(buffer, 0, count);
                            //out.write(buffer, 0, count);
                            totalBytes += count;
                        }
                        zin.closeEntry();
                        fout.close();
                    }
                }
//                int progress = 1 + (total++ * 100 / entries);
                if (size < decompressedSize)
                    size = decompressedSize;
                int progress = (int) ( (totalBytes * 100L / size));
                if (p < progress)
                    zipExtractionCallback.progress(progress, "در حال استخراج از حالت فشرده:");
                p = progress;
            }
            zin.close();
        } catch (Exception e) {
            zipExtractionCallback.error("خطا هنگام عملیات استخراج : " + e.getMessage());
            Log.e(TAG, "unzip", e);
        }
    }

    private void dirChecker(String destination, String dir) {
        File f = new File(destination, dir);

        if (!f.isDirectory()) {
            boolean success = f.mkdirs();
            if (!success) {
                Log.w(TAG, "Failed to create folder " + f.getName());
            }
        }
    }


    public interface ZipExtractionCallback {

        void progress(int progress, String status);

        void finish();

        void error(String error);
    }

}

使用它的例子:

private void ExtractMap(String zipFilePath,Context context) {

    new Thread(new Runnable() {
        @Override
        public void run() {

            ZipUtility zipUtility = new ZipUtility(new ZipUtility.ZipExtractionCallback() {
                @Override
                public void progress(int progress, String status) {
                    ((UpdateActivity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                             //todo handle ui
                        }
                    });
                }

                @Override
                public void finish() {

                    ((UpdateActivity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //todo handle ui
                        }
                    });

                }

                @Override
                public void error(String error) {
                    ((UpdateActivity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                           //todo handle ui
                        }
                    });
                }
            });

            zipUtility.unzipFromPath(context,
                    zipFilePath,
                    context.getFilesDir().getAbsolutePath() + File.separator);


        }
    }).start();
}
于 2019-12-18T09:49:52.727 回答