/*
 * Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
 * and the EPL 1.0 (http://h2database.com/html/license.html).
 * Initial Developer: H2 Group
 */
package org.h2.compress;

import java.util.StringTokenizer;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import org.h2.api.ErrorCode;
import org.h2.message.DbException;

This is a wrapper class for the Deflater class. This algorithm supports the following options:
  • l or level: -1 (default), 0 (no compression), 1 (best speed), ..., 9 (best compression)
  • s or strategy: 0 (default), 1 (filtered), 2 (huffman only)
See also java.util.zip.Deflater for details.
/** * This is a wrapper class for the Deflater class. * This algorithm supports the following options: * <ul> * <li>l or level: -1 (default), 0 (no compression), * 1 (best speed), ..., 9 (best compression) * </li><li>s or strategy: 0 (default), * 1 (filtered), 2 (huffman only) * </li></ul> * See also java.util.zip.Deflater for details. */
public class CompressDeflate implements Compressor { private int level = Deflater.DEFAULT_COMPRESSION; private int strategy = Deflater.DEFAULT_STRATEGY; @Override public void setOptions(String options) { if (options == null) { return; } try { StringTokenizer tokenizer = new StringTokenizer(options); while (tokenizer.hasMoreElements()) { String option = tokenizer.nextToken(); if ("level".equals(option) || "l".equals(option)) { level = Integer.parseInt(tokenizer.nextToken()); } else if ("strategy".equals(option) || "s".equals(option)) { strategy = Integer.parseInt(tokenizer.nextToken()); } Deflater deflater = new Deflater(level); deflater.setStrategy(strategy); } } catch (Exception e) { throw DbException.get(ErrorCode.UNSUPPORTED_COMPRESSION_OPTIONS_1, options); } } @Override public int compress(byte[] in, int inLen, byte[] out, int outPos) { Deflater deflater = new Deflater(level); deflater.setStrategy(strategy); deflater.setInput(in, 0, inLen); deflater.finish(); int compressed = deflater.deflate(out, outPos, out.length - outPos); while (compressed == 0) { // the compressed length is 0, meaning compression didn't work // (sounds like a JDK bug) // try again, using the default strategy and compression level strategy = Deflater.DEFAULT_STRATEGY; level = Deflater.DEFAULT_COMPRESSION; return compress(in, inLen, out, outPos); } deflater.end(); return outPos + compressed; } @Override public int getAlgorithm() { return Compressor.DEFLATE; } @Override public void expand(byte[] in, int inPos, int inLen, byte[] out, int outPos, int outLen) { Inflater decompresser = new Inflater(); decompresser.setInput(in, inPos, inLen); decompresser.finished(); try { int len = decompresser.inflate(out, outPos, outLen); if (len != outLen) { throw new DataFormatException(len + " " + outLen); } } catch (DataFormatException e) { throw DbException.get(ErrorCode.COMPRESSION_ERROR, e); } decompresser.end(); } }