Saturday, June 12, 2021

Zipping Files And Folders in Java

In this post we'll see how to zip files in Java and also how to zip a directory in Java where files and sub-directories are compressed recursively.

In Java, java.util.zip package provides classes for data compression and decompression. For compressing data to a ZIP file ZipOutputStream class can be used. The ZipOutputStream writes data to an output stream in zip format.


Steps to zip a file in Java

  • First you need to create a ZipOutputStream object, to which you pass the output stream of the file you wish to use as a zip file.
  • Then you also need to create an InputStream for reading the source file.
  • Create a ZipEntry for file that is read.
    ZipEntry entry = new ZipEntry(FILENAME)
    Put the zip entry object using the putNextEntry method of ZipOutputStream
  • That's it now you have a connection between your InputStream and OutputStream. Now read data from the source file and write it to the ZIP file.
  • Finally close the streams.

Java Program to zip a single file

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFileDemo {
  static final int BUFFER = 1024;

  public static void main(String[] args) {
   zipFile();
  }
  // Method to zip file
  private static void zipFile(){
    ZipOutputStream zos = null;
    BufferedInputStream bis = null;
    try{
      // source file
      String fileName = "G:\\abc.txt";
      File file = new File(fileName);
      FileInputStream fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis, BUFFER);
          
      // Creating ZipOutputStream
      FileOutputStream fos = new FileOutputStream("G:\\abc.zip");
      zos = new ZipOutputStream(fos);                  
          
      // ZipEntry --- Here file name can be created using the source file
      ZipEntry ze = new ZipEntry(file.getName());
      // Putting zipentry in zipoutputstream
      zos.putNextEntry(ze);
      byte data[] = new byte[BUFFER];
      int count;
      while((count = bis.read(data, 0, BUFFER)) != -1) {
        zos.write(data, 0, count);
      }
    }catch(IOException ioExp){
      System.out.println("Error while zipping " + ioExp.getMessage());
    }finally{
      if(zos != null){
        try {
          zos.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
      if(bis != null){
        try {
          bis.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}
 

Java Program to zip multiple files

In this Java example multiple files are zipped in Java using ZipOutputStream. Each source file is added as a ZipEntry to the ZipOutputStream.

public class ZipFileDemo {
  public static void main(String[] args) {
    try {
      //Source files
      String file1 = "G:/abc.txt";
      String file2 = "G:/Test/abn.txt";
      //Zipped file
      String zipFilename = "G:/final.zip";
      File zipFile = new File(zipFilename);
      FileOutputStream fos  = new FileOutputStream(zipFile);            
      ZipOutputStream zos = new ZipOutputStream(fos);
          
      zipFile(file1, zos);
      zipFile(file2, zos);
      zos.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
    
  // Method to zip file
  private static void zipFile(String fileName, ZipOutputStream zos) throws IOException{
    final int BUFFER = 1024;
    BufferedInputStream bis = null;
    try{
      File file = new File(fileName);
      FileInputStream fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis, BUFFER);          

      // ZipEntry --- Here file name can be created using the source file
      ZipEntry zipEntry = new ZipEntry(file.getName());        
      zos.putNextEntry(zipEntry);
      byte data[] = new byte[BUFFER];
      int count;
      while((count = bis.read(data, 0, BUFFER)) != -1) {
        zos.write(data, 0, count);
      }  
      // close entry every time
      zos.closeEntry();
    } finally{
      try {
        bis.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }  
    }
  }
}

Zipping Directory recursively in Java

If you have a folder structure as given below and you want to zip all the files in the parent folder and its sub folders recursively, then you need to go through the list of files and folders and compress them.

zipping files in Java

For zipping directory in Java two approaches are given here.

  1. You can use Files.walkFileTree() method (Java 7 onward) which recursively visit all the files in a file tree.
  2. You can read files in the folder with in the code and add them to a list and then compress the files with in that list.

Zipping Directory recursively in Java Using Files.walkFileTree()

If you are using Java 7 or higher then you can use Path and Files.walkFileTree() method to recursively zip the files. Using Files.walkFileTree() method makes the code shorter and leaves most of the work to API.

You need to implement FileVisitor interface which is one of the argument of the walkFileTree() method, implementation of two of the methods of FileVisitor is required-

preVisitDirectory- For directories you just need to make entry of the directory path.
visitFile- Zip each visited file.

Here try-with-resources in Java 7 is also used for managing resources automatically.

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFolderSeven {
  // Source folder which has to be zipped
  static final String FOLDER = "G:\\files";
  public static void main(String[] args) {
    ZipFolderSeven zs = new ZipFolderSeven();
    zs.zippingInSeven();
  }
  private void zippingInSeven(){
    // try with resources - creating outputstream and ZipOutputSttream
    try (FileOutputStream fos = new FileOutputStream(FOLDER.concat(".zip"));
        ZipOutputStream zos = new ZipOutputStream(fos)) {            
      Path sourcePath = Paths.get(FOLDER);
      // using WalkFileTree to traverse directory
      Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>(){
        @Override
        public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
          // it starts with the source folder so skipping that 
          if(!sourcePath.equals(dir)){
            //System.out.println("DIR   " + dir);
            zos.putNextEntry(new ZipEntry(sourcePath.relativize(dir).toString() + "/"));            
            zos.closeEntry();    
          }
          return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
          zos.putNextEntry(new ZipEntry(sourcePath.relativize(file).toString()));
          Files.copy(file, zos);
          zos.closeEntry();
          return FileVisitResult.CONTINUE;
        }
      });
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Java code to zip files recursively using list() method

Here is the Java code that goes through the folder structure and zips all files and subfolders recursively. It will even take care of the empty folders in the source folder. In this example list() method of the File class is used.

  • list()- Returns an array of strings naming the files and directories in the directory denoted by this abstract pathname.
Get the list of files and directories with in the parent directory using list() method and then iterate it, for each sub-directory keep calling list() method recursively to compress files in sub-directories.

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFolderDemo {

  static final int BUFFER = 1024;
  // Source folder which has to be zipped
  static final String FOLDER = "G:\\files";
  List<File> fileList = new ArrayList<File>();
  public static void main(String[] args) {    
    ZipFolderDemo zf = new ZipFolderDemo();
    // get list of files
    List<File> fileList = zf.getFileList(new File(FOLDER));
    //go through the list of files and zip them 
    zf.zipFiles(fileList);    
  }
    
  private void zipFiles(List<File> fileList){
    try{
      // Creating ZipOutputStream - Using input name to create output name
      FileOutputStream fos = new FileOutputStream(FOLDER.concat(".zip"));
      ZipOutputStream zos = new ZipOutputStream(fos);
      // looping through all the files
      for(File file : fileList){
        // To handle empty directory
        if(file.isDirectory()){
          // ZipEntry --- Here file name can be created using the source file
          ZipEntry ze = new ZipEntry(getFileName(file.toString())+"/");
          // Putting zipentry in zipoutputstream
          zos.putNextEntry(ze);
          zos.closeEntry();
        }else{
          FileInputStream fis = new FileInputStream(file);
          BufferedInputStream bis = new BufferedInputStream(fis, BUFFER);
          // ZipEntry --- Here file name can be created using the source file
          ZipEntry ze = new ZipEntry(getFileName(file.toString()));
          // Putting zipentry in zipoutputstream
          zos.putNextEntry(ze);
          byte data[] = new byte[BUFFER];
          int count;
          while((count = bis.read(data, 0, BUFFER)) != -1) {
              zos.write(data, 0, count);
          }
          bis.close();
          zos.closeEntry();
        }               
      }                
      zos.close();    
    }catch(IOException ioExp){
      System.out.println("Error while zipping " + ioExp.getMessage());
      ioExp.printStackTrace();
    }
  }
    
  /**
   * This method will give the list of the files 
   * in folder and subfolders
   * @param source
   * @return
   */
  private List<File> getFileList(File source){      
    if(source.isFile()){
      fileList.add(source);
    }else if(source.isDirectory()){
      String[] subList = source.list();
      // This condition checks for empty directory
      if(subList.length == 0){
        //System.out.println("path -- " + source.getAbsolutePath());
        fileList.add(new File(source.getAbsolutePath()));
      }
      for(String child : subList){
        getFileList(new File(source, child));
      }
    }
    return fileList;
  }
    
  /**
   * 
   * @param filePath
   * @return
   */
  private String getFileName(String filePath){
    String name = filePath.substring(FOLDER.length() + 1, filePath.length());
    //System.out.println(" name " + name);
    return name;      
  }
}

That's all for this topic Zipping Files And Folders in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Unzip File in Java
  2. Creating Tar File And GZipping Multiple Files in Java
  3. Reading File in Java Using BufferedReader
  4. How to Read File From The Last Line in Java
  5. Reading File in Java Using Scanner

You may also like-

  1. Java Program to Convert a File to Byte Array
  2. Format Date in Java Using SimpleDateFormat
  3. How to Display Pyramid Patterns in Java - Part1
  4. equals() And hashCode() Methods in Java
  5. final Keyword in Java With Examples
  6. Deadlock in Java Multi-Threading
  7. Lambda Expressions in Java 8
  8. Java ArrayBlockingQueue With Examples