Я хочу сжать / распаковать и сериализовать / десериализовать содержимое строки. Я использую следующие две статические функции.
/**
* Compress data based on the {@link Deflater}.
*
* @param pToCompress
* input byte-array
* @return compressed byte-array
* @throws NullPointerException
* if {@code pToCompress} is {@code null}
*/
public static byte[] compress(@Nonnull final byte[] pToCompress) {
checkNotNull(pToCompress);
// Compressed result.
byte[] compressed = new byte[] {};
// Create the compressor.
final Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_SPEED);
// Give the compressor the data to compress.
compressor.setInput(pToCompress);
compressor.finish();
/*
* Create an expandable byte array to hold the compressed data.
* You cannot use an array that's the same size as the orginal because
* there is no guarantee that the compressed data will be smaller than
* the uncompressed data.
*/
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(pToCompress.length)) {
// Compress the data.
final byte[] buf = new byte[1024];
while (!compressor.finished()) {
final int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
// Get the compressed data.
compressed = bos.toByteArray();
} catch (final IOException e) {
LOGWRAPPER.error(e.getMessage(), e);
throw new RuntimeException(e);
}
return compressed;
}
/**
* Decompress data based on the {@link Inflater}.
*
* @param pCompressed
* input string
* @return compressed byte-array
* @throws NullPointerException
* if {@code pCompressed} is {@code null}
*/
public static byte[] decompress(@Nonnull final byte[] pCompressed) {
checkNotNull(pCompressed);
// Create the decompressor and give it the data to compress.
final Inflater decompressor = new Inflater();
decompressor.setInput(pCompressed);
byte[] decompressed = new byte[] {};
// Create an expandable byte array to hold the decompressed data.
try (final ByteArrayOutputStream bos = new ByteArrayOutputStream(pCompressed.length)) {
// Decompress the data.
final byte[] buf = new byte[1024];
while (!decompressor.finished()) {
try {
final int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
} catch (final DataFormatException e) {
LOGWRAPPER.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
// Get the decompressed data.
decompressed = bos.toByteArray();
} catch (final IOException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
return decompressed;
}
Тем не менее, по сравнению с несжатыми значениями, это на несколько порядков медленнее, даже если я кеширую распакованный результат, а значения распаковываются только, если контент действительно нужен.
То есть он используется для устойчивой древовидной структуры, подобной DOM, и XPath-запросов, которые заставляют декомпрессию значений String примерно в 50 раз, если не больше, медленнее (на самом деле не тестируются, просто выполняются модульные тесты). Мой ноутбук даже зависает после некоторых модульных тестов (каждый раз проверял его примерно 5 раз), потому что Eclipse больше не отвечает из-за интенсивного дискового ввода-вывода, а что нет. Я даже установил уровень сжатия на Deflater.BEST_SPEED
, тогда как другие уровни сжатия могли бы быть лучше, возможно, я предоставляю параметр конфигурации, который можно установить для resources
. Возможно, я что-то напутал, потому что раньше не использовал дефлятор. Я даже сжимаю контент только там, где длина строки> 10.
Edit: После рассмотрения извлечения экземпляра Deflater в статическое поле создается впечатление, что создание экземпляра deflater и inflater является очень дорогостоящим, так как узкое место в производительности устранено и, возможно, без микробенчмарков или тому подобного я могу ' Я не вижу потери производительности :-) Я просто сбрасываю дефлятор / инфлятор перед использованием нового входа.