Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zlib compression Using Deflate and Inflate classes in Java

I want trying to use the Deflate and Inflate classes in java.util.zip for zlib compression.

I am able to compress the code using Deflate, but while decompressing, I am having this error -

Exception in thread "main" java.util.zip.DataFormatException: unknown compression method
    at java.util.zip.Inflater.inflateBytes(Native Method)
    at java.util.zip.Inflater.inflate(Inflater.java:238)
    at java.util.zip.Inflater.inflate(Inflater.java:256)
    at zlibCompression.main(zlibCompression.java:53)

Here is my code so far -

import java.util.zip.*;
import java.io.*;

public class zlibCompression {

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException, DataFormatException {
        // TODO Auto-generated method stub

        String fname = "book1";
        FileReader infile = new FileReader(fname);
        BufferedReader in = new BufferedReader(infile);

        FileOutputStream out = new FileOutputStream("book1out.dfl");
        //BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename));

        Deflater compress = new Deflater();
        Inflater decompress = new Inflater();

        String readFile = in.readLine();
        byte[] bx = readFile.getBytes();

        while(readFile!=null){
            byte[] input = readFile.getBytes();
            byte[] compressedData = new byte[1024];
            compress.setInput(input);
            compress.finish();
            int compressLength = compress.deflate(compressedData, 0, compressedData.length);
            //System.out.println(compressedData);
            out.write(compressedData, 0, compressLength);
            readFile = in.readLine();
        }

        File abc = new File("book1out.dfl");
        InputStream is = new FileInputStream("book1out.dfl");

        InflaterInputStream infl = new InflaterInputStream(new FileInputStream("book1out.dfl"), new Inflater());
        FileOutputStream outFile = new FileOutputStream("decompressed.txt");

        byte[] b = new byte[1024];
        while(true){

            int a = infl.read(b,0,1024);
            if(a==0)
                break;

            decompress.setInput(b);
            byte[] fresult = new byte[1024];
            //decompress.in
            int resLength = decompress.inflate(fresult);
            //outFile.write(b,0,1);
            //String outt = new String(fresult, 0, resLength);
            //System.out.println(outt);
        }

        System.out.println("complete");

    }
}
like image 834
Ashish Agarwal Avatar asked May 30 '11 08:05

Ashish Agarwal


People also ask

How does zlib inflate work?

The decompression algorithm used in zlib is the inflate method, which is the decoding process that takes a deflate bit stream for decompression and correctly produces the original full-size data or file.

How do you deflate in Java?

The deflate() function of the Deflater class in java. util. zip is used to compress the input data and fill the given buffer with the compressed data. The function returns the number of bytes of the compressed data.

What is inflate in Java?

The inflate() function of the Inflater class is used to uncompress the input data and fill the given buffer with the uncompressed data. The function returns the number of bytes of the uncompressed data.

Does gzip use zlib?

zlib was adapted from the gzip code. All of the mentioned patents have since expired. The zlib library supports Deflate compression and decompression, and three kinds of wrapping around the deflate streams.


1 Answers

What are you trying to do here? You use an InflaterInputStream, which decompresses your data, and then you try to pass this decompressed data again to an Inflater? Use either one of them, but not both.

This is what is causing your exception here.

In addition to this, there are quite some minor errors, like these mentioned by bestsss:

  • You finish the compression in the loop - after finishing, no more data can be added.
  • You don't check how much output the deflate process produces. If you have long lines, it could be more than 1024 bytes.
  • You set input to the Inflater without setting the length a, too.

Some more which I found:

  • You don't close your FileOutputStream after writing (and before reading from the same file).
  • You use readLine() to read a line of text, but then you don't add the line break again, which means in your decompressed file won't be any line breaks.
  • You convert from bytes to string and to bytes again without any need.
  • You create variables which you don't use later on.

I won't try to correct your program. Here is a simple one which does what I think you want, using DeflaterOutputStream and InflaterInputStream. (You could also use JZlib's ZInputStream and ZOutputStream instead.)

import java.util.zip.*;
import java.io.*;

/**
 * Example program to demonstrate how to use zlib compression with
 * Java.
 * Inspired by http://stackoverflow.com/q/6173920/600500.
 */
public class ZlibCompression {

    /**
     * Compresses a file with zlib compression.
     */
    public static void compressFile(File raw, File compressed)
        throws IOException
    {
        InputStream in = new FileInputStream(raw);
        OutputStream out =
            new DeflaterOutputStream(new FileOutputStream(compressed));
        shovelInToOut(in, out);
        in.close();
        out.close();
    }

    /**
     * Decompresses a zlib compressed file.
     */
    public static void decompressFile(File compressed, File raw)
        throws IOException
    {
        InputStream in =
            new InflaterInputStream(new FileInputStream(compressed));
        OutputStream out = new FileOutputStream(raw);
        shovelInToOut(in, out);
        in.close();
        out.close();
    }

    /**
     * Shovels all data from an input stream to an output stream.
     */
    private static void shovelInToOut(InputStream in, OutputStream out)
        throws IOException
    {
        byte[] buffer = new byte[1000];
        int len;
        while((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
    }


    /**
     * Main method to test it all.
     */
    public static void main(String[] args) throws IOException, DataFormatException {
        File compressed = new File("book1out.dfl");
        compressFile(new File("book1"), compressed);
        decompressFile(compressed, new File("decompressed.txt"));
    }
}

For more efficiency, it might be useful to wrap the file streams with buffered streams. If this is performance critical, measure it.

like image 78
Paŭlo Ebermann Avatar answered Sep 22 '22 17:09

Paŭlo Ebermann