1

I am having trouble using Deflater to write a GZIP file. I created a default header and used CRC32 to keep track of the checksum.

The file I am zipping is smaller than my buffer, but the output I get for this compressor is ~200 bytes larger than it should be (gzip creates a file of 457 bytes while my code is creating a file of 652 bytes. I printed the compressedSize and it says it was 634 bytes) I did a hexdump on my final file, and it says that both my trailer and my main file is incorrect, but my header is correct. I am not allowed to use GZIPOutputStream for this assignment, but I used it's code to write the header and trailer. The amount of bytes read in is correct.

The "manage" object is an object that does the reading and writing from System.in and System.out in a synchronized matter (this is for multithreading), and I verified that they should read and write a file in order. I looked at the GZIPOutputStream source and the DeflaterOutputStream source, and my code looks similar, so I am unsure why my compressor is giving me such a large compressed byte array. I played with the Deflater levels and the strategies, but they give me the same result.

EDIT: The constructor for my Deflater is Deflater compressor = new Deflater(Deflater.DEFAULT_LEVEL, true);

CRC32 checksum = new CRC32();
                    checksum.reset();
                    int uncompressedLength = 0;

                    uncompressedLength = manage.read(buff, threadNum, prime);

                    if (uncompressedLength > 0)
                    {
                        checksum.update(buff, 0, uncompressedLength);
                        compressor.setInput(buff);
                        compressor.finish();                        
                         byte[] output = new byte[BUFFER_SIZE];
                        compressor.deflate(output);
                        int compressedDataLength = (int) compressor.getBytesWritten();


                        manage.write(output, compressedDataLength, threadNum, (int) checksum.getValue(), uncompressedLength);
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
am3692
  • 61
  • 1
  • 4
  • Which compression level are you using? May be gzip just uses BEST_COMPRESSION = 9? – Robert Oct 26 '11 at 18:09
  • I tried all levels, but I still get ~630 bytes of output from the compressor. According to GZIPOutputStream, default level should be fine – am3692 Oct 26 '11 at 18:12
  • 1
    This question has already been answered [here](http://stackoverflow.com/questions/13387215/iterable-gzip-deflate-inflate-in-java). – Keith Morgan Jan 16 '13 at 16:33

1 Answers1

1

The Deflater class has three constructors. The one with two arguments uses a boolean that, if true, indicates ZLIB header and checksum fields should not be used, which is what GZIP needs. The other two constructors (one no-args, the other only specifying compression level) default to using those header and checksum fields. In other words, it's like the two-args constructor with false. Maybe try the one with the boolean and set it to true?

Here's the constructor doc.

G_H
  • 11,739
  • 3
  • 38
  • 82
  • I forgot to put it in the code I posted, but I used this contructor compressor = new Deflater(Deflater.DEFAULT_COMPRESSION, true); – am3692 Oct 26 '11 at 21:36
  • @am3692 No idea what's going on then. Sorry. – G_H Oct 26 '11 at 21:40