Сжатая строка в PHP не совпадает со сжатой строкой в ​​Java - PullRequest
1 голос
/ 05 ноября 2019

Сжатие слова «test» в php возвращает «eNorSS0uAQAEXQHB» с использованием строки

base64_encode (gzcompress ("test", 9))

Я хочу то же самоеПодход в Android-приложение тоже. Таким образом, я использовал ниже код:

try {
byte[] input = "test".getBytes("UTF-8");
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
compresser.deflate(output);
compresser.end();
return Base64.encodeToString(output, Base64.DEFAULT);
} catch (Exception e) {
return e.getMessage();
}

получать выход как

eJzLz0sFAAKRAUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ==


Попробованная другой подход, как показано ниже:

try {
 ByteArrayOutputStream out = new ByteArrayOutputStream(str.length());
 GZIPOutputStream gzip = new GZIPOutputStream(out);
 gzip.write(str.getBytes());
 gzip.close();

 byte[] compressedBytes = out.toByteArray();
 return Base64.encodeToString(compressedBytes, Base64.DEFAULT); // I would return compressedBytes instead String
 } catch (Exception e) {
     return e.getMessage();
 }

получение вывода в виде

H4sIAAAAAAAAAMvPSwUA8YZsegMAAAA =

Какой подход следует использовать для получения такого же сжатия из Java (как в php) => eNorSS0uAQAEXQHB

1 Ответ

0 голосов
/ 05 ноября 2019

У вашего подхода есть две проблемы.

  1. код не использует одинаковый уровень сжатия (PHP-> 9, Java-> 6 (по умолчанию))
  2. длина сжатых данных (возвращаемых compresser.deflate(output)) игнорируется

Вот подробный рабочий пример для создания того же вывода Base64 в Java, что и ваш фрагмент PHP.

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.zip.Deflater;

public class CompressDemo {
    public static void main(String[] args) throws Exception {
        byte[] input = "test".getBytes(StandardCharsets.UTF_8);
        byte[] buffer = new byte[100];
        // create a deflater for the compression to best compression level (9)
        Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);
        compresser.setInput(input);
        compresser.finish();
        // keep the length of the compressed data
        int compressedDataLength = compresser.deflate(buffer);
        compresser.end();
        // create an array only containing the compressed bytes
        byte[] compressed = Arrays.copyOfRange(buffer, 0, compressedDataLength);
        System.out.println(new String(Base64.getEncoder().encode(compressed)));
    }
}

edit Пример, когда буфер слишком мал, чтобы хранить все сжатые данные за один проход.

public static void main(String[] args) throws Exception {
    ByteArrayOutputStream resultBuffer = new ByteArrayOutputStream();
    byte[] input = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(StandardCharsets.UTF_8);
    // a buffer to small to hold the compressed data
    byte[] buffer = new byte[10];
    Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);
    compresser.setInput(input);
    compresser.finish();
    do {
        // compress the input data and fill the buffer
        int compressedDataLength = compresser.deflate(buffer);
        System.out.println("compressedDataLength = " + compressedDataLength);
        // append the compressed data to the result buffer
        resultBuffer.write(buffer, 0, compressedDataLength);
        // continue until all input data were processed
    } while(!compresser.finished());
    compresser.end();
    byte[] compressed = resultBuffer.toByteArray();
    System.out.println(new String(Base64.getEncoder().encode(compressed)));
}

output

compressedDataLength = 10
compressedDataLength = 10
compressedDataLength = 10
compressedDataLength = 4
eNpzdHJ2cXVz9/D08vbx9fMPCAwKDgkNC4+IjAIAZKYH4A==
...