Android:获取Zip中的文件数量?

时间:2011-07-22 19:57:04

标签: java android zip android-assets

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

我的'assets'文件夹中有一个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() - 方法,但它需要一个文件路径,因为我的文件位于'assets'文件夹中我很漂亮确定从这个目录中读取的唯一方法是通过流式传输。

我有办法实现这个目标吗?

4 个答案:

答案 0 :(得分:8)

感谢您的回答。我最终使用:AssetFileDescriptor API来获取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..
}

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

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

答案 1 :(得分:4)

使用ZipFile API,有size方法可返回ZipEntriesZipFile的数量。您可以从assets文件夹中读取。

示例:

int zipEntriesCount(String path) throws IOException {

     ZipFile zf= new ZipFile(path);
     return zf.size();
}

答案 2 :(得分:3)

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

您是否考虑过progressBar.setMax(zin.getSize())然后跟踪您拨打progressBar.setProgress()时写的字节数,而不是您读过多少个文件?这应该可以解决您的问题,并为您(imho)提供更准确的进度条。

答案 3 :(得分:0)

这是我基于@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();
}