February 4, 2024

How to Zip a Folder in Java

In the post How to Zip Files in Java we have seen how to zip a single file or multiple files in Java but you may also need to zip a folder in Java where you also retain the folder tree structure while zipping it. This post shows how to zip a folder in Java where the zip archive contains the whole tree structure (files and subdirectories).

Options for zipping a folder in Java

For zipping a folder with all its subfolders and files two options are given in this post.

  1. Using Files.walkFileTree() method- Using this method you can recursively visit all the files in a file tree. An implementation of FileVisitor interface is provided to the Files.walkFileTree method to visit each file in a file tree. This option is available Java 7 onward. See example.
  2. By providing the code yourself to read the files with in a folder recursively by using listFiles() method in java.io.File class. See example.

Check this post How to Unzip a File in Java to see how to unzip files and folders in Java.

Directory structure used

Java programs shown here to zip a folder in Java use the following directory structure.

zip a folder in Java

With in the parent folder there is one sub folder Child with two files and one file is stored in the parent folder. The zipped archive should retain the same tree structure.

Using Files.walkFileTree method to zip a folder in Java

One of the argument of this method is a FileVisitor interface. You do need to provide implementation of this interface as per your requirement. FileVisitor interface has four methods, for zipping a folder you do need to implement two of them.

  • preVisitDirectory– Invoked before a directory's entries are visited. By implementing this method you can create the visited folder with in the zip archive.
  • visitFile– Invoked on the file being visited. By implementing this method you can add each visited file to the zip archive.
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipOutputStream;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;

public class ZipFolder {
  public static void main(String[] args) {
    // Source folder
    final String SOURCE_DIR = "F:/knpcode/Parent";
    // creating the name of the zipped archive
    String ZIP_DIR = SOURCE_DIR.concat(".zip");
    zipFolderStructure(SOURCE_DIR, ZIP_DIR);
  }
    
  private static void zipFolderStructure(String sourceFolder, String zipFolder){
    // Creating a ZipOutputStream by wrapping a FileOutputStream
    try (FileOutputStream fos = new FileOutputStream(zipFolder); 
         ZipOutputStream zos = new ZipOutputStream(fos)) {
      Path sourcePath = Paths.get(sourceFolder);
      // Walk the tree structure using WalkFileTree method
      Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>(){
        @Override
        // Before visiting the directory create the directory in zip archive
        public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
          // Don't create dir for root folder as it is already created with .zip name 
          if(!sourcePath.equals(dir)){
            System.out.println("Directory- " + dir);
            zos.putNextEntry(new ZipEntry(sourcePath.relativize(dir).toString() + "/"));                  
            zos.closeEntry();    
          }
          return FileVisitResult.CONTINUE;
        }
        @Override
        // For each visited file add it to zip entry
        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
          System.out.println("File Name- " + sourcePath.relativize(file).toString());
          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();
    }
  }
}
Output
Directory- F:\knpcode\Parent\Child
File Name- Child\hello.txt
File Name- Child\Project.docx
File Name- Test.txt

Zip a folder in Java by listing files recursively

In the code you first create a list of all the files and folders residing with in a parent folder. To go through the list of files with in a directory listFiles() method of java.io.File class is used.

Once you have this folder tree structure in a list you iterate through that list to create a zip archive. For every iterated element of the list you check if it is a directory or a file-

  • If it is a directory then you just add the name of the directory in the zip archive.
  • If it is a file then you add the name as well as the content of the file.
public class ZippingFolder {
  List fileList = new ArrayList();
  public static void main(String[] args) {	
    // Source folder
    final String ROOT_DIR = "F:/knpcode/Parent";
    // creating the name of the zipped archive
    String ZIP_DIR = ROOT_DIR.concat(".zip");
    ZippingFolder zippingFolder = new ZippingFolder();
    // get the list of the whole folder structure
    zippingFolder.getListOfFiles(new File(ROOT_DIR));
    zippingFolder.zipTreeStructure(ROOT_DIR, ZIP_DIR);
  }
	
  private void zipTreeStructure(String ROOT_DIR, String zipDir){
    final int BUFFER = 1024;
    BufferedInputStream bis = null;
    ZipOutputStream zos = null;
    try{
      // Creating ZipOutputStream by wrapping FileOutputStream
      FileOutputStream fos = new FileOutputStream(zipDir);
      zos = new ZipOutputStream(fos);
      // iterating the folder tree structure
      for(File file : fileList){
        // If directory
        if(file.isDirectory()){
          // add the directory name as zipentry
          ZipEntry ze = new ZipEntry(file.getName()+"/");             
          zos.putNextEntry(ze);
          zos.closeEntry();
        }
        // If file
        else{
          FileInputStream fis = new FileInputStream(file);
          bis = new BufferedInputStream(fis, BUFFER);                
          ZipEntry ze = new ZipEntry(getFileName(ROOT_DIR, file.toString()));                   
          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();
        }               
      }                
           
    }catch(IOException ioExp){
      ioExp.printStackTrace();
    } finally{
      try {
        zos.close(); 
        if(bis != null)
          bis.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }  
    }
  }
  // Method to get the folder tree structure
  private void getListOfFiles(File source){
    File[] fileNames = source.listFiles();
    for(File file : fileNames){
      if(file.isDirectory()){
        fileList.add(file);
        // recursive call to go through the subdirectory structure
        getListOfFiles(file);
      }else{
        fileList.add(file);
      }
    }
  }
    
  // To get the relative file path 
  private String getFileName(String ROOT_DIR, String filePath){
    String name = filePath.substring(ROOT_DIR.length() + 1, filePath.length());
    return name;
  }
}

That's all for the topic How to Zip a Folder in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment