v7db.files.Compression.java Source code

Java tutorial

Introduction

Here is the source code for v7db.files.Compression.java

Source

/**
 * Copyright (c) 2011-2012, Thilo Planz. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package v7db.files;

import static java.util.zip.Deflater.BEST_COMPRESSION;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Compression {

    // minimum overhead: 10 byte header, 8 byte trailer
    static final int GZIP_STORAGE_OVERHEAD = 18;

    static Logger log = LoggerFactory.getLogger(Compression.class);

    /**
     * @return 0, if the "deflated" data fills the whole output array
     */
    static int deflate(byte[] data, int off, int len, byte[] out) {
        Deflater deflater = new Deflater(BEST_COMPRESSION, true);
        deflater.setInput(data, off, len);
        deflater.finish();
        int size = deflater.deflate(out);
        if (size == 0 || size == out.length)
            return 0;
        return size;
    }

    /**
     * @return null, if the "gzipped" data is larger than the input (or there
     *         has been an exception)
     */
    public static byte[] gzip(byte[] data, int off, int len) {

        if (len < GZIP_STORAGE_OVERHEAD)
            return null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length);
            GZIPOutputStream gz = new GZIPOutputStream(baos);
            gz.write(data, off, len);
            gz.close();
            if (baos.size() >= len)
                return null;
            return baos.toByteArray();
        } catch (Exception e) {
            log.error("failed to gzip byte array", e);
            return null;
        }
    }

    /**
     * assumes that the result buffer has exactly the needed size
     * 
     * @throws DataFormatException
     */
    static void inflate(byte[] data, int off, int len, byte[] out) throws DataFormatException {
        Inflater inflater = new Inflater(true);
        inflater.setInput(data, off, len);
        int size = inflater.inflate(out);
        if (size != out.length)
            throw new DataFormatException(
                    "unexpected size of deflated data: " + size + " instead of " + out.length);
    }

    static void gunzip(InputStream in, OutputStream out) throws IOException {
        IOUtils.copy(new GZIPInputStream(in), out);
    }

    /**
     * input must be in zip format, i.e. first a local header, and then the data
     * segment.
     * 
     */
    static InputStream unzip(InputStream in) throws IOException {
        ZipInputStream zip = new ZipInputStream(in);
        zip.getNextEntry();
        return zip;
    }

    /**
     * @return the compressed file (delete after use), or null, if the
     *         "compressed" data is bigger than the input (or if there was an
     *         exception)
     */

    static File gzip(File data) {
        File file = null;
        try {
            file = File.createTempFile(data.getName(), ".gz");
            OutputStream out = new GZIPOutputStream(new FileOutputStream(file));
            long size = FileUtils.copyFile(data, out);
            out.close();
            long cSize = file.length();
            if (cSize < size) {
                return file;
            }
            file.delete();
            return null;
        } catch (Exception e) {
            log.error("failed to gzip file " + data, e);
            if (file != null)
                file.delete();
            return null;
        }
    }

}