30/08/2014

[Java] zip file or directory (with subdirectories)

Note: it is possible to perform zip operation with standard Java libraries, but more superfluous steps are required (ie: more streams have to be handled).

A simple way to zip a file or folder (with or without subdirectories) maintaining the folders structure is using the Apache Commons Compress library.

 import java.util.*;  
 import java.io.*;  
 import org.apache.commons.compress.utils.IOUtils;  
 import org.apache.commons.compress.archivers.*;  
 import org.apache.commons.compress.archivers.zip.*;  
   
 public void zip(String location, String name, String ziplocation, String zipname){  
      //method variables  
      private OutputStream out;  
      private ArchiveOutputStream zip_out;  
      private File f;  
   
      //out writes the final file, zip_out creates the zip archive  
   out = new FileOutputStream(new File(ziplocation+File.separator+zipname+".zip"));  
   zip_out = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, out);  
      //zip it  
      File f = new File(location+File.separator+name);  
      //first time baseDir is empty  
      dozip(f, "");  
      //close archive  
      zip_out.finish();   
      out.close();  
 }  
   
 //aux method for zipping  
 private void dozip(File myFile, String baseDir) throws Exception{  
      //maintain the directory structure while zipping  
      String entryName = baseDir+myFile.getName();  
      //DO NOT do a putArchiveEntry for folders as it is not needed  
      //if it's a directory then list and zip the contents. Uses recursion for nested directories  
      if(myFile.isDirectory() == true){  
           File[] filesList = myFile.listFiles();  
           if(filesList != null){  
                for (File file : filesList) {  
                     dozip(file, entryName+File.separator);  
                }  
           }  
      }  
      else{  
           //add file  
           zip_out.putArchiveEntry(new ZipArchiveEntry(myFile, entryName));  
           IOUtils.copy(new FileInputStream(myFile), zip_out);  
           zip_out.closeArchiveEntry();  
      }  
 }  


It has to be recursive so that we can handle subdirectories correctly. The resulting zipped file will unzip to the same exact folder structure originally zipped. If you pass the location and ziplocation parameters with the path separator already appended, there's no need to concatenate File.separator in the code.

No comments:

Post a Comment

With great power comes great responsibility