How to Zip a folders and download - java

I have implemented the download of files. It is downloading and saving it to memory.
Now my problem is, if there is folder and sub folder, I need to ZIP the folder and download the zip file and save it in memory. I tried lot but I did'nt find a solution. Can any one can guide me to get the solution?
Here my download single file code...
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
ZipOutputStream zos = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP "
+ connection.getResponseCode() + " "
+ connection.getResponseMessage();
}
String fileName = tvtitle.getText().toString();
String fileExtension = tvtype.getText().toString();
File imageDirectory = new File(Path);
imageDirectory.mkdirs();
int fileLength = connection.getContentLength();
String _path = Path;
input = connection.getInputStream();
File outputFile = new File(_path, fileName + fileExtension);
output = new FileOutputStream(outputFile);
// zos = new ZipOutputStream(output);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
if (isCancelled()) {
input.close();
return null;
}
total += count;
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}

first add permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
call this method by passing "inputFolderPath" and "outputFolderPath"
private static void zipFolder(String inputFolderPath, String outZipPath) {
try {
FileOutputStream fos = new FileOutputStream(outZipPath);
ZipOutputStream zos = new ZipOutputStream(fos);
File srcFile = new File(inputFolderPath);
File[] files = srcFile.listFiles();
Log.d("", "Zip directory: " + srcFile.getName());
for (int i = 0; i < files.length; i++) {
Log.d("", "Adding file: " + files[i].getName());
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(files[i]);
zos.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
zos.close();
} catch (IOException ioe) {
Log.e("", ioe.getMessage());
}
}

Related

Compressing a folder into a ZipFile

I have this Java method to upload a file. I am trying to cater for users trying to upload a folder by compressing that folder into a zip file and upload it instead. For some reason in my case file.isDirectory() and file.isFile() are not working correctly.. even though the filename does not contain any extension, file.isFile() is returning true and isDirectory() returns false. Also directory.list() is also acting weird by returning null.
What can be the problem? Am I doing something wrong?
public File uploadFile(FileItem item, String filename, int ticket_id) throws IOException
{
FileOutputStream out = null;
InputStream fileContent = null;
File file = null;
try
{
//fullpath returns C://MyDocuments//zerafbe//Documents//apache-tomcat-7.0.29//webapps//attachments//t50\test
StringBuffer fullPath = new StringBuffer();
fullPath.append(Attachment.attachments_path);
fullPath.append("t");
fullPath.append(Integer.toString(ticket_id));
fullPath.append(File.separator);
fullPath.append(filename);
System.out.println("filename " + filename);
file = new File(fullPath.toString());
if (!file.exists())
{
// if directory does not exist, create it
file.getParentFile().mkdirs();
}
if (file.isFile())
{
// if file is not a folder
out = new FileOutputStream(file);
fileContent = item.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
// read all the file and write it to created file
while ((read = fileContent.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
}
else if (file.isDirectory())
{
ZipFile appZip = new ZipFile(fullPath.toString());
appZip.generateFileList(file);
appZip.zipIt(filename + ".zip");
}
}
catch (FileNotFoundException e)
{
LogFile.logError("[FileUpload.uploadFile()] " + e.getMessage());
}
catch (IOException e1)
{
LogFile.logError("[FileUpload.uploadFile()] " + e1.getMessage());
}
finally
{
if (out != null)
{
out.close();
}
if (fileContent != null)
{
fileContent.close();
}
}
return file;
}
This is the ZipFile class I am using
public class ZipFile
{
List<String> fileList = null;
String source_folder = "";
public ZipFile(String source_folder)
{
fileList = new ArrayList<String>();
this.source_folder = source_folder;
}
public void zipIt(String zipFile)
{
byte[] buffer = new byte[1024];
String source = "";
try
{
try
{
source = source_folder.substring(source_folder.lastIndexOf("\\") + 1, source_folder.length());
}
catch(Exception e)
{
source = source_folder;
}
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
for (String file : this.fileList)
{
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(source_folder + File.separator + file);
int len;
while ((len = in.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
in.close();
}
zos.closeEntry();
//remember close it
zos.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
public void generateFileList(File node)
{
// add file only
if(node.isFile())
{
fileList.add(generateZipEntry(node.toString()));
}
if(node.isDirectory())
{
String[] subNode = node.list();
if (subNode != null) {
for(String filename : subNode)
{
generateFileList(new File (node, filename));
}
}
}
}
private String generateZipEntry(String path)
{
return path.substring(source_folder.length() + 1, path.length());
}
}
file.list() is being done in the generateFileList method in ZipFile class. I know this is returning null since I tried detecting whether the file is a folder or a file by using filename.indexOf(".") instead of isDirectory() and isFile() since they were not working. But I wish I had an explanation for this.
Thanks for your help!
if (!file.exists()) {
// if directory does not exist, create it
file.mkdirs();
}
will create directory and test file.isDirectory() will return true
It could be a problem with the path?
C://MyDocuments//zerafbe//Documents//apache-tomcat-7.0.29//webapps//attachments//t50\test
You are mixing backslash with slash...
I tested your code block
ZipFile appZip = new ZipFile(file.toString());
appZip.generateFileList(file);
appZip.zipIt(filename + ".zip");
with a local folder and it's working perfectly. I think you are passing a invalid path. This may be the cause isFile or isDirectory methods are acting strangely. Try to add a validation statement at the starting of generateFileList method using File API:
if(!node.exists) {
// return some flag to signify error OR throw a suitable Exception
}
This should work.
public String compressData(String srcDir) {
String zipFile = srcDir+".zip";
try {
// create byte buffer
byte[] buffer = new byte[1024];
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
File dir = new File(srcDir);
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
System.out.println("Adding file: " + files[i].getName());
FileInputStream fis = new FileInputStream(files[i]);
// begin writing a new ZIP entry, positions the stream to the start of the entry data
zos.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
// close the InputStream
fis.close();
}
// close the ZipOutputStream
zos.close();
}
catch (IOException ioe) {
System.out.println("Error creating zip file" + ioe);
}
return zipFile;
}

How to write files to an SD Card from the internet?

An example would be a simple image.
I have tried so many things and it just refuses to work despite making a whole lot of sense.
What I've done so far is I'm able to grab 25 pictures and add them to
/sdcard/app name/sub/dir/filename.jpg
They all appear there according to the DDMS but they always have a filesize of 0.
I'm guessing it's probably because of my input stream?
Here's my function that handles the downloading and saving.
public void DownloadPages()
{
for (int fileC = 0; fileC < pageAmount; fileC++)
{
URL url;
String path = "/sdcard/Appname/sub/dir/";
File file = new File(path, fileC + ".jpg");
int size=0;
byte[] buffer=null;
try{
url = new URL("http://images.bluegartr.com/bucket/gallery/56ca6f9f2ef43ab7349c0e6511edb6d6.png");
InputStream in = url.openStream();
size = in.available();
buffer = new byte[size];
in.read(buffer);
in.close();
}catch(Exception e){
}
if (!new File(path).exists())
new File(path).mkdirs();
FileOutputStream out;
try{
out = new FileOutputStream(file);
out.write(buffer);
out.flush();
out.close();
}catch(Exception e){
}
}
}
It just keeps giving me 25 files in that directory but all of their file sizes are zero. I have no idea why. This is practically the same code I've used in a java program.
PS...
If you're gonna give me a solution... I've already tried code like this. It doesn't work.
try{
url = new URL(urlString);
in = new BufferedInputStream(url.openStream());
fout = new FileOutputStream(filename);
byte data[] = new byte[1024];
int count;
System.out.println("Now downloading File: " + filename.substring(0, filename.lastIndexOf(".")));
while ((count = in.read(data, 0, 1024)) != -1){
fout.write(data, 0, count);
}
}finally{
System.out.println("Download complete.");
if (in != null)
in.close();
if (fout != null)
fout.close();
}
}
Here's an image of what my directories look like
http://oi48.tinypic.com/2cpcprm.jpg
A bit change to your second option, try it as following way,
byte data[] = new byte[1024];
long total = 0;
int count;
while ( ( count = input.read(data)) != -1 )
{
total += count;
output.write( data,0,count );
}
This one is different in while statement while ((count = in.read(data, 0, 1024)) != -1)
Using Guava something like this should work:
String fileUrl = "xxx";
File file = null;
InputStream in;
FileOutputStream out;
try {
Uri url = new URI(fileUrl);
in = url.openStream();
out = new FileOutputStream(file)
ByteStreams.copy(in, out);
}
catch (IOException e) {
System.out.println(e.toString());
}
finally {
in.close();
out.flush();
out.close();
}

ZipInputStream getNextEntry is null when extracting .zip files

I'm trying to extract .zip files and I'm using this code:
String zipFile = Path + FileName;
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
UnzipCounter++;
if (ze.isDirectory()) {
dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(Path
+ ze.getName());
while ((Unziplength = zin.read(Unzipbuffer)) > 0) {
fout.write(Unzipbuffer, 0, Unziplength);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
but the problem is that, while debugging, when the code reaches the while(!=null) part, the zin.getNextEntry() is always null so it doesnt extract anything..
The .zip file is 150kb.. How can I fix this?
The .zip exists
Code I use to dl the .zip:
URL=intent.getStringExtra("DownloadService_URL");
FileName=intent.getStringExtra("DownloadService_FILENAME");
Path=intent.getStringExtra("DownloadService_PATH");
File PathChecker = new File(Path);
try{
if(!PathChecker.isDirectory())
PathChecker.mkdirs();
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
lenghtOfFile/=100;
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Path+FileName);
byte data[] = new byte[1024];
long total = 0;
int count = 0;
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
total += count;
notification.setLatestEventInfo(context, contentTitle, "جاري تحميل ملف " + FileName + " " + (total/lenghtOfFile), contentIntent);
mNotificationManager.notify(1, notification);
}
output.flush();
output.close();
input.close();
You might have run into the following problem, which occurs, when reading zip files using a ZipInputStream: Zip files contain entries and additional structure information in a sequence. Furthermore, they contain a registry of all entries at the very end (!) of the file. Only this registry does provide full information about the correct zip file structure. Therefore, reading a zip file in a sequence, by using a stream, sometimes results in a "guess", which can fail. This is a common problem of all zip implementations, not only for java.util.zip. Better approach is to use ZipFile, which determines the structure from the registry at the end of the file. You might want to read http://commons.apache.org/compress/zip.html, which tells a little more details.
If the Zip is placed in the same directory as this exact source, named "91.zip", it works just fine.
import java.io.*;
import java.util.zip.*;
class Unzip {
public static void main(String[] args) throws Exception {
String Path = ".";
String FileName = "91.zip";
File zipFile = new File(Path, FileName);
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
int UnzipCounter = 0;
while ((ze = zin.getNextEntry()) != null) {
UnzipCounter++;
//if (ze.isDirectory()) {
// dirChecker(ze.getName());
//} else {
byte[] Unzipbuffer = new byte[(int) pow(2, 16)];
FileOutputStream fout = new FileOutputStream(
new File(Path, ze.getName()));
int Unziplength = 0;
while ((Unziplength = zin.read(Unzipbuffer)) > 0) {
fout.write(Unzipbuffer, 0, Unziplength);
}
zin.closeEntry();
fout.close();
//}
}
zin.close();
}
}
BTW
what is the language in that MP3, Arabic?
I had to alter the source to get it to compile.
I used the File constructor that takes two String arguments, to insert the correct separator automatically.
Try this code:-
private boolean extractZip(String pathOfZip,String pathToExtract)
{
int BUFFER_SIZE = 1024;
int size;
byte[] buffer = new byte[BUFFER_SIZE];
try {
File f = new File(pathToExtract);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(pathOfZip), BUFFER_SIZE));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = pathToExtract +"/"+ ze.getName();
if (ze.isDirectory()) {
File unzipFile = new File(path);
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
}
else {
FileOutputStream out = new FileOutputStream(path, false);
BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
try {
while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
}catch (Exception e) {
Log.e("Exception", "Unzip exception 1:" + e.toString());
}
finally {
fout.flush();
fout.close();
}
}
}
}catch (Exception e) {
Log.e("Exception", "Unzip exception2 :" + e.toString());
}
finally {
zin.close();
}
return true;
}
catch (Exception e) {
Log.e("Exception", "Unzip exception :" + e.toString());
}
return false;
}
This code works fine for me. Perhaps you need to check that the zipFile String is valid?
String zipFile = "C:/my.zip";
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
System.out.println("got entry " + ze);
}
zin.close();
produced valid results on a 3.3Mb zip file.
This code seems to work correctly for me.
Are you sure that your zip file is a valid zip file? If the file does not exist or is not readable then you will get a FileNotFoundException, but if the file is empty or not a valid zip file, then you will get ze == null.
while ((ze = zin.getNextEntry()) != null) {
The zip that you specify isn't a valid zip file. The size of the entry is 4294967295
while ((ze = zin.getNextEntry()) != null) {
System.out.println("ze=" + ze.getName() + " " + ze.getSize());
UnzipCounter++;
This gives:
ze=595.mp3 4294967295
...
Exception in thread "main" java.util.zip.ZipException: invalid entry size (expected 4294967295 but got 341297 bytes)
at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:386)
at java.util.zip.ZipInputStream.read(ZipInputStream.java:156)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at uk.co.farwell.stackoverflow.ZipTest.main(ZipTest.java:29)
Try your code with a valid zip file.
I know it's late for answer but anyway ..
I think the problem is in
if(!PathChecker.isDirectory())
PathChecker.mkdirs();
it should be
if(!PathChecker.getParentFile().exists())
PathChecker.getParentFile().mkdirs();

Android:"Unexpected end of stream" exception downloading large files

I am building an Android Application and I need to download a file from a url, which is 33 MB large.
Here the download task:
try {
int MAX_BUFFER_SIZE = 4096;
URL mUrl = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
connection.setRequestMethod("GET");
long length = connection.getContentLength(), downloaded = 0;
int read;
byte [] buffer = new byte[(((int)length) > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : (int)length];
String filename = getFilename(mUrl);
File file = new File (SDCARD_ROOT);
if (!file.exists() || !file.isDirectory()){
file.mkdir();
}
this.filename = filename;
file = new File (SDCARD_ROOT + this.filename);
FileOutputStream fos = new FileOutputStream (file);
//Start downloading
InputStream stream = connection.getInputStream();
while ((read=stream.read(buffer)) > -1){
fos.write(buffer, 0, read);
downloaded += read;
publishProgress((int) ((float) downloaded/length * 100));
}
fos.close();
return 1;
} catch (Exception e){
Log.e("REV-PARTS", "Revolver parts error in DownloadTask: " + e.getMessage());
return 2;
}
It works right with small files (1-15 MB), but it will return a "unexpected end of stream" exception with large files.
Setting a chunk size seemed to work for me.
connection.setChunkedStreamingMode(1048576);
For large files you need to set the connection time out manually by using the following code.
I have set the time out to 3 minutes
connection.setConnectTimeout(180000);
connection.setReadTimeout(180000);
While you catch the exception, I try the method downContinue(). I can show my code:
private void downloadApk() {
thread1 = new Thread() {
public void run() {
File oFile = null;
try {
URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
ReadableByteChannel channel =
Channels.newChannel(urlConnection.getInputStream());
oFile =
new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/" + "hy_ht_new/" + "test2" + ".apk");
oFile.setWritable(true);
oFile.setReadable(true);
if (oFile.exists()) {
oFile.delete();
}
FileOutputStream fos = new FileOutputStream(oFile);
fileSize = urlConnection.getContentLength();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int noOfBytes = 0;
byte[] data = null;
sendApkMessage(0, 0);
while ((noOfBytes = channel.read(buffer)) > 0) {
data = new byte[noOfBytes];
System.arraycopy(buffer.array(), 0, data, 0, noOfBytes);
buffer.clear();
fos.write(data, 0, noOfBytes);
downLoadFileSize += noOfBytes;
sendApkMessage(1, downLoadFileSize);
}
fos.flush();
fos.close();
channel.close();
sendApkMessage(2, oFile.getAbsolutePath());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
downContinue();
}
};
};
thread1.start();
}
private void downContinue() {
continueTime++;
try {
if (continueTime == 3) {
continueTime = 0;
sendApkMessage(4, 0);
Log.e("what is the continuetime", "continueTime" + continueTime);
} else {
URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
File oFile =
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
+ "hy_ht_new/" + "test2" + ".apk");
RandomAccessFile oSavedFile = new RandomAccessFile(oFile, "rw");
FileOutputStream fos = new FileOutputStream(oFile);
ReadableByteChannel channel = Channels.newChannel(urlConnection.getInputStream());
// oSavedFile.seek(nPos);
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte[] data = null;
int temp = 0;
sendApkMessage(3, oFile.getAbsolutePath());
while ((temp = channel.read(buffer)) > 0) {
data = new byte[temp];
System.arraycopy(buffer.array(), 0, data, 0, temp);
buffer.clear();
fos.write(data, 0, temp);
}
fos.flush();
fos.close();
oSavedFile.close();
sendApkMessage(2, oFile.getAbsolutePath());
continueTime = 0;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("what is the exception", e.toString() + continueTime);
downContinue();
}
}
This downContinue method is used to solve this problem. At least, the file is downloaded successfully!

How to speed up unzipping time in Java / Android?

Unzipping files on android seems to be dreadfully slow. At first I thought this was just the emulator but it appears to be the same on the phone. I've tried different compression levels, and eventually dropped down to storage mode but it still takes ages.
Anyway, there must be a reason! Does anyone else have this problem? My unzip method looks like this:
public void unzip()
{
try{
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
File rootfolder = new File(directory);
rootfolder.mkdirs();
ZipEntry ze = null;
while ((ze = zin.getNextEntry())!=null){
if(ze.isDirectory()){
dirChecker(ze.getName());
}
else{
FileOutputStream fout = new FileOutputStream(directory+ze.getName());
for(int c = zin.read();c!=-1;c=zin.read()){
fout.write(c);
}
//Debug.out("Closing streams");
zin.closeEntry();
fout.close();
}
}
zin.close();
}
catch(Exception e){
//Debug.out("Error trying to unzip file " + zipFile);
}
}
I don't know if unzipping on Android is slow, but copying byte for byte in a loop is surely slowing it down even more. Try using BufferedInputStream and BufferedOutputStream - it might be a bit more complicated, but in my experience it is worth it in the end.
BufferedInputStream in = new BufferedInputStream(zin);
BufferedOutputStream out = new BufferedOutputStream(fout);
And then you can write with something like that:
byte b[] = new byte[1024];
int n;
while ((n = in.read(b,0,1024)) >= 0) {
out.write(b,0,n);
}
Thanks for the solution Robert.
I modified my unzip method and now it takes only a few seconds instead of 2 minutes.
Maybe someone's interested in my solution. So here you go:
public void unzip() {
try {
FileInputStream inputStream = new FileInputStream(filePath);
ZipInputStream zipStream = new ZipInputStream(inputStream);
ZipEntry zEntry = null;
while ((zEntry = zipStream.getNextEntry()) != null) {
Log.d("Unzip", "Unzipping " + zEntry.getName() + " at "
+ destination);
if (zEntry.isDirectory()) {
hanldeDirectory(zEntry.getName());
} else {
FileOutputStream fout = new FileOutputStream(
this.destination + "/" + zEntry.getName());
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zipStream.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
zipStream.closeEntry();
bufout.close();
fout.close();
}
}
zipStream.close();
Log.d("Unzip", "Unzipping complete. path : " + destination);
} catch (Exception e) {
Log.d("Unzip", "Unzipping failed");
e.printStackTrace();
}
}
public void hanldeDirectory(String dir) {
File f = new File(this.destination + dir);
if (!f.isDirectory()) {
f.mkdirs();
}
}
Using above ideas and ideas from some other sources I have created this class
Create this new class
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import android.util.Log;
public class DecompressFast {
private String _zipFile;
private String _location;
public DecompressFast(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zin.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
bufout.close();
zin.closeEntry();
fout.close();
}
}
zin.close();
Log.d("Unzip", "Unzipping complete. path : " +_location );
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
Log.d("Unzip", "Unzipping failed");
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}
}
USAGE
just pass your file location of zip file and your destination Location to this class
example
String zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip file location
String unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; // unzip location
DecompressFast df= new DecompressFast(zipFile, unzipLocation);
df.unzip();
Dont Forget to add following permissions in manifest(also Run time permission if version higher than marshmellow)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
hope this helps
The URL that helped me learn how to zip and unzip can be found here.
I used that URL in conjuction with user3203118's answer above for unzipping. This is for future references for people who run in to this issue and need help solving it.
Below is the ZipManager code I am using:
public class ZipManager {
private static final int BUFFER = 80000;
public void zip(String[] _files, String zipFileName) {
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(zipFileName);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
byte data[] = new byte[BUFFER];
for (int i = 0; i < _files.length; i++) {
Log.v("Compress", "Adding: " + _files[i]);
FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_files[i].substring(_files[i]
.lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void unzip(String _zipFile, String _targetLocation) {
// create target location folder if not exist
dirChecker(_targetLocation);
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
// create dir if required while unzipping
if (ze.isDirectory()) {
dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(
_targetLocation + "/" + ze.getName());
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zin.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
zin.closeEntry();
bufout.close();
fout.close();
}
}
zin.close();
} catch (Exception e) {
System.out.println(e);
}
}
private void dirChecker(String dir) {
File f = new File(dir);
if (!f.isDirectory()) {
f.mkdirs();
}
}
}
Just call this method and it will give you much better performance..
public boolean unzip(Context context) {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
BufferedInputStream in = new BufferedInputStream(zin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if (ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location
+ ze.getName());
BufferedOutputStream out = new BufferedOutputStream(fout);
byte b[] = new byte[1024];
for (int c = in.read(b,0,1024); c != -1; c = in.read()) {
out.write(b,0,c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
return true;
} catch (Exception e) {
Log.e("Decompress", "unzip", e);
return false;
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if (!f.isDirectory()) {
f.mkdirs();
}
}
In case of using BufferedOutputStream be sure to flush it. If you do not do it, size smaller than buffer will not be unzipped properly
if (ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location
+ ze.getName());
BufferedOutputStream out = new BufferedOutputStream(fout);
byte buffer[] = new byte[1024];
for (int c = in.read(buffer,0,1024); c != -1; c = in.read()) {
out.write(buffer,0,c);
}
out.flush();//flush it......
zin.closeEntry();
fout.close();
}

Categories