Wednesday, March 20, 2024

How to create a ZIP File in Java? ZipEntry and ZipOutputStream Compression Example

Since compressing and archiving old log files is an essential housekeeping job in any Java application environment, a Java programmer should know how to compress files in .zip format and then how to read them programmatically if required. The JDK provides full support to create and read ZIP files in Java. There is a separate package java.util.zip to hold all classes related to zipping and unzipping files and streams. In this series of articles, you will learn how to use those classes like ZipFile, ZipEntry, ZipInputStream, and ZipOutputStream, etc. 

This is the second article about how to work with compressed archives in Java e.g. .zip files. In the last article, I have shown you how to read ZIP archives in Java, and today, I'll teach you how to compress files in the ZIP file format by yourself using a Java program. You will compress a bunch of text files to create a .zip file by using JDK's ZIP file support classes.

You create a .zip file in Java to archive files and directories in compressed format. The JDK (Java Development Kit) provides the necessary classes to make a zip file in the java.util.zip package.

Your case uses ZipEntry, ZipFile, and ZipOutputStream classes to compress files and create a zip archive. But before that, let's some important classes and their functions.
  • java.util.zip.ZipFile - This class is used to read entries from a zip file. 
  • java.util.zip.ZipEntry - This class is used to represent a ZIP file entry.
  • java.util.zip.ZipInputStream - This class implements an input stream filter for reading files in the ZIP file format. Includes support for both compressed and uncompressed entries.
  • java.util.zip.ZipOutPutStream - This class implements an output stream filter for writing files in the ZIP file format. Includes support for both compressed and uncompressed entries.

Btw, the java.util.zip package not only provides classes to read and write files compressed in ZIP format but also classes to read/write GZIP format classes as well like GZIPInputStream and GZIPOutputStream. We'll learn about them in some upcoming tutorials. 

Unlike there were two ways to read ZIP files in Java, like by using ZipInputStream and ZipFile, there is only one way to create a Zip files in Java i.e. by using ZipOutputStream. This class writes data to an output stream in the ZIP file format. If you want to store data in a file, you must chain ZipOutputStream to a FileOutputStream, similar to what we do in the Decorator pattern.

Once you create the zip output stream, the next step will be to open source text files that you want to compress. You have to create a zip entry for each file using the java.util.zip.ZipEntry class and before you write the data to stream, you must first put the zip entry object using the putNextEntry() method of ZipOutputStream. Once this is done, you can write the data and close the stream.

So, these were the three steps you need to follow to compress a text file and create a ZIP file in Java i.e.
  1. Create a FileOutputStream to create a zip file
  2. Pass that FileOutputStream to ZipOutputStream to write data in zipping file format. 
  3. Optionally you can wrap FileOutputStream into BufferedOutputStream for better write performance.
  4. Open each source file using File class
  5. Create a ZipEntry by using those File objects
  6. Put the ZipEntry into ZipOutputStream using putNextEntry() method
  7. write the data to the ZIP file using write() method of ZipOutputStream.
  8. close the stream

We'll see the complete code example of creating a zip file in Java in the next section to see these steps in action.




How to Create a Zip file in Java Program? Example

Here is our complete Java program to package files in a ZIP file in Java. In this program, we have a couple of text files and a directory with a file in the Eclipse project directory. We'll compress those files and directories to create a compressed file in ZIP file format. 

You can use this file similar to the .zip file created by WinZip or WinRAR utility which archives files using ZIP format. You can even open them using any zip tool e.g. Winzip, WinRAR, or 7Zip, etc.

Anyway, here is the screenshot of the files and directory which will be compressed to create a ZIP file in Java:

How to create a ZIP File Format in Java?


The files which will be compressed are names.txt, java7.txt, and java.txt. I'll also include the directory targetrr, which contains an apache.txt file, just to demonstrate that you can also include subdirectories with files while zipping them.  

Unfortunately, these files are not large so you won't see the effect of compression e.g. compressing a 1GB text file to create a ZIP file in KB (kilo bytes), but you can do that yourself. Just copy the log file you want to compress in the archive directory and run the program.


Java Program to create a ZIP File in Java

package demo;

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

/**
 * Java Program to demonstrate how to create ZIP file in Java. ZIP file contains
 * individual files in compressed format.
 * 
 * @author java67
 */

public class FileCopyDemo {

    public static void main(String args[]) {

        try {
            // let's create a ZIP file to write data
            FileOutputStream fos = new FileOutputStream("sample.zip");
            ZipOutputStream zipOS = new ZipOutputStream(fos);

            String file1 = "names.txt";
            String file2 = "java7.txt";
            String file3 = "targetrr/apache.txt";
            String file4 = "java.txt";

            writeToZipFile(file1, zipOS);
            writeToZipFile(file2, zipOS);
            writeToZipFile(file3, zipOS);
            writeToZipFile(file4, zipOS);

            zipOS.close();
            fos.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Add a file into Zip archive in Java.
     * 
     * @param fileName
     * @param zos
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static void writeToZipFile(String path, ZipOutputStream zipStream)
            throws FileNotFoundException, IOException {

        System.out.println("Writing file : '" + path + "' to zip file");

        File aFile = new File(path);
        FileInputStream fis = new FileInputStream(aFile);
        ZipEntry zipEntry = new ZipEntry(path);
        zipStream.putNextEntry(zipEntry);

        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipStream.write(bytes, 0, length);
        }

        zipStream.closeEntry();
        fis.close();
    }
}

Ouput :
Writing file : 'names.txt' to zip file
Writing file : 'java7.txt' to zip file
Writing file : 'targetrr/apache.txt' to zip file
Writing file : 'java.txt' to zip file


If you open this ZIP file in your machine using WinZIP or WinRAR you can see that it contains all three files and the single directory with a file we have just added, as shown below:

ZipFile, ZipEntry and ZipOutputStream Compression Example


Important Points

Some useful important points related to compression, archiving, and how to work with compressed files e.g. ZIP and GZIP files in Java:

1. Compression and archiving are two different things, but Windows tools like Winzip does both i.e. they compress the files and archive them into a separate file.

2. In UNIX, you have to use separate commands for archiving and compression-like tar command is used for archiving and gzip is used to compress the archived file.

3. Files added to a ZIP/JAR file are compressed individually

4. The JDK support both ZIP and GZIP file formats, It provides classes to read, create and modify ZIP and GZIP file formats. For example,  you can use ZipInputStream /ZipOutputStream to read/write ZIP file format and GZIPInputStream and GZIPOutputStream to read/write compressed data in GZIP file format.


That's all about how to create a zip file in Java. It's similar to creating a zip file in windows by using the Winzip tool. You can use this program to archive old log files to save some space on your Web Server. You can also enhance this program to accept the input and output location like the location to pick files and where to create the output files. Don't forget to compress the file using GZIP format its more efficient and will likely result in more space saving specially if you are archiving large log files with size of Giga bytes. 

If you are facing any error while creating zip archive in Java or If you have any questions feel free ask in comments. 


5 comments:

  1. what to do if i have to download this zip file?

    ReplyDelete
  2. how to preserve file permissions?

    ReplyDelete
  3. How to zip files only without directories?

    ReplyDelete
  4. How to zip files only without directories?

    ReplyDelete
    Replies
    1. Instead of including the whole file path just include the file name in the zipEntry like this:

      ZipEntry zipEntry = new ZipEntry(aFile.getName());

      Delete

Feel free to comment, ask questions if you have any doubt.