Android: Get Number Of Files Within Zip?
Solution 1:
Thanks for the answers. What I ended up doing using the: AssetFileDescriptor
API to get the file size of the zip file and setting that as the ProgessBar.setMax()
value. Then as I loop through the zip contents I increment the progress by using each entries file size. This works but the only concern I have is that the AssetFileDescriptor.getLength()
value as well as the ZipEntry.getSize()
values return a long
value so I am forced to cast them to an integer before I can set the max and/or increment the ProgessBar
so there is a slight possibility I might overload an integer value causing an exception but this is not likely because I do not anticipate my file sizes ever getting bigger than the max holding capacity of an integer.
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..
}
Not the best solution but it works.
I'm aware of the ZipFile
API but it requires a string to be passed in but I am not sure what the path is to that directory or how to get it?
Solution 2:
Use ZipFile
API, There is a size
method that returns the number of ZipEntries
in the ZipFile
. You can read from assets folder.
example:
int zipEntriesCount(String path) throws IOException {
ZipFile zf= new ZipFile(path);
return zf.size();
}
Solution 3:
Your basic problem seems to be that you have to do progressBar.setMax()
before you start reading the file, and you are setting the max based on the number of files.
Have you thought about doing progressBar.setMax(zin.getSize())
and then keeping track of how many bytes you've written when you call progressBar.setProgress()
, instead of how many files you've read? This should solve your problem and will give you (imho) a more accurate progress bar.
Solution 4:
this is my solution based on @davorb idea which is to show progress based on file size and not content of zip file.
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);
}
}
Example of using it :
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();
}
Post a Comment for "Android: Get Number Of Files Within Zip?"