All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.sb1.troxy.common.CompressedString Maven / Gradle / Ivy

package no.sb1.troxy.common;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A String compressed using the ZLIB algorithm, used to save memory for exceptionally large Strings.
 * If the String is below a certain length no compression is done.
 */
public class CompressedString {
    private static final Logger log = LoggerFactory.getLogger(CompressedString.class);
    private static final int MIN_COMPRESS_SIZE = 32768;
    private final CharSequence text;

    public CompressedString(String text) {
        this.text = text == null || text.length() < MIN_COMPRESS_SIZE ? text : new ZlibString(text);
    }

    @Override
    public String toString() {
        return text.toString();
    }

    private class ZlibString implements CharSequence {
        private static final String ENCODE_CHARSET = "ISO-8859-1";  // charset doesn't matter as long as it's inflated using the same charset, iso-8859-1 is probably faster than utf-8
        private int inflateSize;
        private byte[] data;

        public ZlibString(String text) {
            try {
                Deflater deflater = new Deflater();
                byte[] tmp = text.getBytes(ENCODE_CHARSET);
                inflateSize = tmp.length;
                deflater.setInput(tmp);
                deflater.finish();
                tmp = new byte[MIN_COMPRESS_SIZE];
                ByteArrayOutputStream baos = new ByteArrayOutputStream(MIN_COMPRESS_SIZE);
                while (true) {
                    int written = deflater.deflate(tmp);
                    if (written > 0)
                        baos.write(tmp, 0, written);
                    else
                        break;
                }
                deflater.end();
                data = baos.toByteArray();
                log.info("Compressed text from {} bytes to {} ({}%)", inflateSize, data.length, data.length * 100 / inflateSize);
            } catch (UnsupportedEncodingException e) {
                log.error("Unable to compress string", e);
            }
        }

        @Override
        public int length() {
            return toString().length();
        }

        @Override
        public char charAt(int index) {
            return toString().charAt(index);
        }

        @Override
        public CharSequence subSequence(int start, int end) {
            return toString().subSequence(start, end);
        }

        @Override
        public String toString() {
            try {
                Inflater inflater = new Inflater();
                inflater.setInput(data);
                byte[] tmp = new byte[inflateSize];
                inflater.inflate(tmp);
                inflater.end();
                return new String(tmp, ENCODE_CHARSET);
            } catch (UnsupportedEncodingException | DataFormatException e) {
                log.error("Unable to compress string", e);
            }
            return "";
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy