Need help?

I'm available for remote short term contracting or consultancy work. Please check out my LinkedIn profile for more details on my experience.

Please feel free to use the form below to contact me.




Zipping Files with Android (Programmatically)

One majorly annoying issue that I stumbled upon, was the fact that I couldn't send multiple attachments using Intents to the Google Mail app. The quickest way around that was of course to compress all of the files into one (ZIP).

After searching around online, I didn't really find much on zipping files on your Android device - most of the articles were for standard java applications, which assumed that all your files were in the current directory that you wanted to zip.

So, I used what I could and whipped up my own wrapper class that allows you to easily zip files in Android!

Here is the class:


import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class Compress {
  private static final int BUFFER = 2048;

  private String[] _files;
  private String _zipFile;

  public Compress(String[] files, String zipFile) {
    _files = files;
    _zipFile = zipFile;
  }

  public void zip() {
    try  {
      BufferedInputStream origin = null;
      FileOutputStream dest = new FileOutputStream(_zipFile);

      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();
    }

  }

}

If that all makes sense to you already, then you probably won't be interested in my explanations below, otherwise, keep reading. :)


private static final int BUFFER = 2048;

private String[] _files;
private String _zipFile;

These are the properties that I've declared for the class.

The first is the BUFFER (for reading the data and writing it to the zip stream), second is the _files array, which will hold all the files (path as well) that will be zipped up, and the third is the name of the zip file (path as well).


public Compress(String[] files, String zipFile) {
  _files = files;
  _zipFile = zipFile;
}

This is the constructor, which is the first thing that gets called when instantiating the class - you'll pass it an array of the files you wish to zip, and a string of what the name of the final zip file will be. It then saves this data in the properties, to be used when you call the zip method.


BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(_zipFile);

ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

byte data[] = new byte[BUFFER];

Next we move into the zip method - the first things we do is setup our BufferedInputStream, which we'll be using to read the data from the file input stream (each file in the files array).

The FileOutputStream creates the zip file, and sets up the stream, which we then pass to the ZipOutputStream for writing to.

If you want more in depth details about each of these objects (classes), then do a quick search for FileOutputStream or ZipOutputStream in Google.


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();

And here we have the main loop, which will go through each file in the _files array and compress each one into the zip file.

Here we first setup a FileInputStream for reading the files - the BufferedInputStream will manage the amount of data that it'll be reading at a time (based on the BUFFER).

The ZipEntry is used for adding the actual file/directory structure - for example, if you add '/mnt/sdcard/data/myzip.zip', it would actually create that directory structure in the zip file, so if you want to just add the file into the root of the zip, you'll need to parse it out. Personally, I just used substring, and lastIndexOf to grab the file at the end.

Once the entry is set, you can add it to the zip output stream using out.putNextEntry.

Now we have another loop, which will be used for reading the data, 2048 bytes at a time, and write it to the zip output stream (to the new entry location).

Finally, we clean up - close the streams.

I hope that made sense, and if I can change anything to make it more understandable, please let me know.

Check out my other article, if you want to find out how to unzip files - Unzipping Files with Android (Programmatically)


jon | June 12, 2010 | Comments (16)

Comments

tht is cool, but Iam still can't Use it in my WordPress. with wp-costum-login-logo tht just for change the WP logo not for ipetmmenling ur image Form. any one can help me with this case?!
Comment by Suellen - October 17, 2012 @ 9:32 pm
How can i use this to zip a directory that contains directories in it, and zip all the content of the original directory( including files in child directories?
Comment by redalin - August 20, 2012 @ 10:17 am
its working ...once again thank u very much ...
Comment by Anand JK - August 08, 2012 @ 4:16 pm
Thank for the code it helps me lot
Comment by Anand - August 08, 2012 @ 4:15 pm
Site de TV por Assinatura TV Digital no PC
Comment by Amanda - April 26, 2012 @ 12:02 am
i'm using ur code here to zip up images and ftp them to an ftp server. with some android phones it works perfect, others i get invalid zip files/corrupt zip files, etc....any idea why this code would work on some phones and not others? seems strange to me!
Comment by Matt - May 10, 2011 @ 10:37 am
Very true! Makes a cahnge to see someone spell it out like that. :)
Comment by Micheal - May 06, 2011 @ 8:39 pm
If I want to use wildcards (ie. zip *.log into logs.zip) how can I use the compress class?
Comment by Nika - March 09, 2011 @ 8:14 pm
This is great! I have it working just fine.But when i m trying to zip a Folder which contains other files and folders then it throws an exception that
"it is a directory" can u please Help Me????
Thanks
Comment by Hamid - March 04, 2011 @ 3:56 pm
I just wrote another article on how to unzip files - http://jondev.net/articles/Unzipping_Files_with_Android_(Programmatically)
Comment by Jon - October 27, 2010 @ 4:30 pm
This is great! I have it working just fine. However, I too would like to see how to extract the zip file and save in a folder.
Comment by Rob - September 01, 2010 @ 1:34 pm
Nice work! Wouldn't mind the corresponding programmatic unzip!
Comment by Paul - August 12, 2010 @ 3:34 pm
Example usage:

String zipName = "/sdcard/zipname.zip";

String[] files = new String[] {"/sdcard/files/file_one.jpg", "/sdcard/files/file_two.gif"};

Compress c = new Compress(files, "zipname.zip");
c.zip();
Comment by Jon - June 24, 2010 @ 10:24 am
Sorry for the delay Burt - I'll add an example to the article later today.

I was on vacation and didn't get around to viewing the comments.
Comment by Jon - June 24, 2010 @ 10:16 am
Would you please show us a quick example of how to use this class? I tried both as having this as an internal class and as a helper (read: external) class.
Comment by Burt Shaw - June 17, 2010 @ 1:13 pm
Can you show us an example use? I'm not seeing how to use this. Compress (myarray, "zipnamehere"); does not work. What am I missing? Thanks
Comment by Burt - June 15, 2010 @ 8:39 pm

Name (required)
Email (will not be published) (required)
Website

captcha