This question already has an answer here:
My application is downloading zip file from the server and extract this zip file and save files into sd card but problem is if i am downloading 4-5 MB zip files and extract it, this is working good but if i am downloading 30-35 MB zip file this will give me error, sorry for my bad English communication.
The Below is my Code for Download & Unzip Zip File:-
public class UnzipManager {
private static String BASE_FOLDER;
public static Context localContext;
public static String passurl;
public static int count;
public static Context context;
/*
* You can use this flag to check whether Unzippingthread is still running..
*/
public static boolean isDownloadInProgress;
/*
* After unzipping using this flag ,you can check whether any low memory
* exceptions Occurred or not..and alert user accordingly..
*/
public static boolean isLowOnMemory;
public static int i = 0;
public static ZipEntry zipEntry;
public static void startUnzipping(Context ctx, int c, String url) {
context = ctx;
count = c;
/*
* MAKE SURE THAT localContext VARIABLE HAS BEEN INITIALIZED BEFORE
* INVOKING THIS METHOD.
*
* ALSO MAKE SURE YOU HAVE SET "INTERNET" AND "NETWORK ACCESS STATE"
* PERMISSIONS IN APPLICATION'S MANIFEST FILE.
*/
Log.d("DEBUG", "In startUnzipping()");
UnzipManager.BASE_FOLDER = Environment.getExternalStorageDirectory()
+ File.separator + "samples";
/*
*
*/
Log.d("DEBUG", "BASE_FOLDER:" + UnzipManager.BASE_FOLDER);
UnzipManager.isLowOnMemory = false;
// Start unzipping in a thread..which is safer
// way to do high cost processes..
passurl = url;
new UnzipThread().start();
}
private static class UnzipThread extends Thread {
@Override
public void run() {
UnzipManager.isDownloadInProgress = true;
Log.d("DEBUG", "Unzipping----------------------------");
URLConnection urlConnection;
try {
/************************************************
*
* IF you are unzipping a zipped file save under some URL in
* remote server
* **********************************************/
URL finalUrl = new URL(passurl
/* Url string where the zipped file is stored... */);
urlConnection = finalUrl.openConnection();
// Get the size of the ( zipped file's) inputstream from
// server..
int contentLength = urlConnection.getContentLength();
Log.d("DEBUG", "urlConnection.getContentLength():"
+ contentLength);
/*****************************************************
*
* YOU CAN GET INPUT STREAM OF A ZIPPED FILE FROM ASSETS FOLDER
* AS WELL..,IN THAT CASE JUST PASS THAT INPUTSTEAM OVER
* HERE...MAKE SURE YOU HAVE SET STREAM CONTENT LENGTH OF THE
* SAME..
*
******************************************************/
ZipInputStream zipInputStream = new ZipInputStream(
urlConnection.getInputStream());
/*
* Iterate over all the files and folders
*/
for (zipEntry = zipInputStream.getNextEntry(); zipEntry != null; zipEntry = zipInputStream
.getNextEntry()) {
Log.d("DEBUG", "Extracting: " + zipEntry.getName() + "...");
/*
* Extracted file will be saved with same file name that in
* zipped folder.
*/
String innerFileName = BASE_FOLDER + File.separator
+ zipEntry.getName();
File innerFile = new File(innerFileName);
/*
* Checking for pre-existence of the file and taking
* necessary actions
*/
if (innerFile.exists()) {
Log.d("DEBUG",
"The Entry already exits!, so deleting..");
innerFile.delete();
}
/*
* Checking for extracted entry for folder type..and taking
* necessary actions
*/
if (zipEntry.isDirectory()) {
Log.d("DEBUG", "The Entry is a directory..");
innerFile.mkdirs();
} else {
Log.d("DEBUG", "The Entry is a file..");
FileOutputStream outputStream = new FileOutputStream(
innerFileName);
final int BUFFER_SIZE = 2048;
/*
* Get the buffered output stream..
*/
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
outputStream, BUFFER_SIZE);
/*
* Write into the file's buffered output stream ,..
*/
int count = 0;
byte[] buffer = new byte[BUFFER_SIZE];
while ((count = zipInputStream.read(buffer, 0,
BUFFER_SIZE)) != -1) {
bufferedOutputStream.write(buffer, 0, count);
}
/***********************************************
* IF YOU WANT TO TRACK NO OF FILES DOWNLOADED, HAVE A
* STATIC COUNTER VARIABLE, INITIALIZE IT IN
* startUnzipping() before calling startUnZipping(), AND
* INCREMENT THE COUNTER VARIABLE OVER HERE..LATER YOU
* CAN USE VALUE OF COUNTER VARIABLE TO CROSS VERIFY
* WHETHER ALL ZIPPED FILES PROPERLY UNZIPPED AND SAVED
* OR NOT.
*
* ************************************************
*/
/*
* Handle closing of output streams..
*/
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
/*
* Finish the current zipEntry
*/
zipInputStream.closeEntry();
}
/*
* Handle closing of input stream...
*/
zipInputStream.close();
Log.d("DEBUG", "--------------------------------");
Log.d("DEBUG", "Unzipping completed..");
i = 1;
} catch (IOException e) {
Log.d("DEBUG", "Exception occured: " + e.getMessage());
if (e.getMessage().equalsIgnoreCase("No space left on device")) {
UnzipManager.isLowOnMemory = true;
}
e.printStackTrace();
}
MainActivity.pd.dismiss();
((MainActivity)context).finish();
UnzipManager.isDownloadInProgress = false;
}
};
}
Logcat Error is:-
02-17 12:21:16.835: D/DEBUG(20562): Exception occured: /mnt/sdcard/samples/iPhone_zendura_Q4a/0.png (No such file or directory)
02-17 12:21:16.835: W/System.err(20562): java.io.FileNotFoundException: /mnt/sdcard/samples/iPhone_zendura_Q4a/0.png (No such file or directory)
02-17 12:21:16.906: W/System.err(20562): at org.apache.harmony.luni.platform.OSFileSystem.open(Native Method)
02-17 12:21:16.906: W/System.err(20562): at dalvik.system.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:94)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:165)
02-17 12:21:16.906: W/System.err(20562): at java.io.FileOutputStream.<init>(FileOutputStream.java:144)
02-17 12:21:16.906: W/System.err(20562): at com.android.screens.UnzipManager$UnzipThread.run(UnzipManager.java:129)
I wrote an
IntentService
that dose both the things together with progress :Add following Service class to your Application (also declare it in your app's Manifest file) :
Sample use case :
Also you can use (if required) FileUtils.java
Don't Delete the file if exists (because the files will be overwritten) or instantiate innerFile again.
Deleting innerFile you lose the file and when trying to create directory using innerFile causes the FileNotFoundException.
This is the final code using the performance improvement answer, it decompressed a 23 MB file into a 130 MB folder in exactly 1 minute:
As JoxTraex said: the error is really obvious.
In
UnzipManager
line 129 you try to open a file that is not there. Thats why you get aFileNotFoundException
. You should check your zip file if it is a correct one and can be extracted correctly on your PC.Try to debug, too. Add a break point on that line and let the application debug and watch what happens there when the specific file location appears.