Java File Compression Example

0

In this article, we will see how to compress data to a zip file using java.util.zip package. Classes in the java.util.zip package allow you to read, create, and modify ZIP and GZIP file formats. It also provides utility classes for computing checksums of arbitrary input streams that can be used to validate input data.

Checksum

In this example, we will compress files and add them to an archive. If you want to send the zipped file to a remote location using checksum value of the zip file one can figure whether the received file is intact or corrupted.
A checksum or hash sum is a small-size datum from a block of digital data for the purpose of detecting errors which may have been introduced during its transmission or storage. The algorithm that computes the checksum on a given data input is called a checksum function. If the computed checksum for the sent zip file doesn’t match with the checksum of the decompressed zip file then there is a very high probability the data has not been accidentally altered or corrupted.

Compressing files to a ZIP File

We will introduce here some of the important classes in the java.util.zip package.

  1. ZipOutputStream – Writes data to an output stream in a ZIP format.
  2. CheckedOutputStream – An output stream that maintains the checksum of the data being written
  3. Adler32 – Implement the java.util.zip.Checksum interface and computes the checksum required for data compression.. The other implementation is CRC32
  4. ZipEntry – Represents a zip file entry

Now that we know the classes involved, lets look into the steps.

  1. Since we want to write data to a zip file, we need to first create a ZipOutputStream object, to which we pass the output stream of the file we wish to write to.
    FileOutputStream dest = new FileOutputStream("allFiles.zip");
    ZipOutputStream zos = new ZipOutputStream(dest);
    
  2. We also want to compute checksum, so we create a CheckedOutputStream object using the file output stream and then pass CheckedOutputStream object while creating the ZipOutputStream object.
    FileOutputStream dest = new FileOutputStream("allFiles.zip");
    CheckedOutputStream checksum = new CheckedOutputStream(dest, new Adler32());
    ZipOutputStream zos = new ZipOutputStream(checksum);
    
  3. Once the target zip output stream is created, the next step is to open each source data file that want to be part of the zip file.
    String[] zipEntryFiles = new String[] { "emp.xml", "x.properties", "y.txt" };
    ...
                for (String zipEntryFile : zipEntryFiles) {                
                    BufferedInputStream bis = new BufferedInputStream(
                            FileCompressionExample.class
                                    .getResourceAsStream(zipEntryFile));
                    try {
                        ...
                    } finally {
                        ...
                    }
                }
    
  4. Before we can write data to the ZIP output stream, we must first put the zip entry object using the putNextEntry() method.
    String fileName =  "com/javarticles/io/" + zipEntryFile;
    ZipEntry entry = new ZipEntry(fileName);
    System.out.println("Adding file: " + fileName);
    zos.putNextEntry(entry);
    
  5. Write the data to the ZIP file.
    int count;
    while ((count = bis.read(data, 0, data.length)) != -1) {
        bos.write(data, 0, count);
    }
    
  6. Finally flush the output stream and close the source stream.
    try {
    ...
    while ((count = bis.read(data, 0, data.length)) != -1) {
        bos.write(data, 0, count);
    }
    } finally {
        bis.close();
        bos.flush();
    }
    

Just to spice up the example, we will add three different types of file to the zip file. An xml, a property file and a text file.

emp.xml:

<?xml version="1.0"?>
<employees>
	<employee id="1">
		<name>Joe</name>
		<age>34</age>
	</employee>
	<employee id="2">
		<name>Sam</name>
		<age>24</age>
	</employee>
	<employee id="3">
		<name>John<!-- author --> S</name>
		<age>44</age>
	</employee>
</employees>

x.properties:

name=javarticles.com

y.txt:

Hello!

FileCompressionExample:

package com.javarticles.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileCompressionExample {
    public static void main(String[] args) throws IOException {
        String[] zipEntryFiles = new String[] { "emp.xml", "x.properties", "y.txt" };

        FileOutputStream dest = new FileOutputStream("allFiles.zip");
        CheckedOutputStream checksum = new CheckedOutputStream(dest,
                new Adler32());
        ZipOutputStream zos = new ZipOutputStream(checksum);
        BufferedOutputStream bos = new BufferedOutputStream(zos);        
        try {
            zos.setComment("Javaticles - Compressing files example");
            byte[] data = new byte[1024];
            for (String zipEntryFile : zipEntryFiles) {                
                BufferedInputStream bis = new BufferedInputStream(
                        FileCompressionExample.class
                                .getResourceAsStream(zipEntryFile));
                try {
                    String fileName =  "com/javarticles/io/" + zipEntryFile;
                    ZipEntry entry = new ZipEntry(fileName);
                    System.out.println("Adding file: " + fileName);
                    zos.putNextEntry(entry);
                    int count;
                    while ((count = bis.read(data, 0, data.length)) != -1) {
                        bos.write(data, 0, count);
                    }
                } finally {
                    bis.close();
                    bos.flush();
                }
            }
            System.out
                    .println("checksum: " + checksum.getChecksum().getValue());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bos.close();
        }

    }
}

The computed checksum must match the checksum computed as we decompress the files.

Output:

Adding file: com/javarticles/io/emp.xml
Adding file: com/javarticles/io/x.properties
Adding file: com/javarticles/io/y.txt
checksum: 3365432775

Download the source code

This was an example about compressing data files to a zip file.

You can download the source code here: fileCompressExample.zip

About Author

Ram’s expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring.
You can reach him at [email protected]

Comments are closed.