12

簡単に思える質問がありますが、適切に機能させることができないようです。

「資産」フォルダー内に解凍する必要がある zip ファイルがありProgessBar、進行状況をユーザーに表示したいファイルがあります。

ProgessBarすべてが機能していますが、最大値を zip ファイル内のファイル数に設定したいと考えています。このフォルダー内のファイルの数は時々変わるのでProgessBar、zip 内に含まれるファイルの数に比例するようにします。

-APIを使用してZipInputStreamいますが、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);
    }

これは機能しますが、基本的に同じことを行う 2 つの while ループがあると少し冗長に思えます。

ZipFile-メソッドを持つ -APIがあることは知っていsize()ますが、ファイルへのパスが必要です。私のファイルは「資産」フォルダー内にあるため、このディレクトリから読み取る唯一の方法はストリーミングによるものだと確信しています。

これを達成する方法はありますか?

4

4 に答える 4

9

答えてくれてありがとう。APIを使用しAssetFileDescriptorて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..
}

最善の解決策ではありませんが、機能します。

APIについては認識していZipFileますが、文字列を渡す必要がありますが、そのディレクトリへのパスや取得方法がわかりません。

于 2011-07-25T16:35:46.527 に答える
5

ZipFileAPIを利用してsize、 の個数を返すメソッドがあります。assets フォルダーから読み取ることができます。ZipEntriesZipFile

例:

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()ことはありますか? これで問題が解決し、(imho)より正確な進行状況バーが表示されます。

于 2011-07-23T02:40:23.870 に答える
1

これは、zipファイルの内容ではなくファイルサイズに基づいて進行状況を表示するという@davorbのアイデアに基づく私のソリューションです。

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 に答える