Я пытаюсь распаковать объект json в Java, который был изначально сжат в PHP. Вот как это сжимается в PHP:
function zip_json_encode(&$arr) {
$uncompressed = json_encode($arr);
return pack('L', strlen($uncompressed)).gzcompress($uncompressed);
}
и декодируется (снова в PHP):
function unzip_json_decode(&$data) {
$uncompressed = @gzuncompress(substr($data,4));
return json_decode($uncompressed, $array_instead_of_object);
}
Это помещается в MySQL, и теперь он должен быть извлечен из базы данных Java. Мы вытаскиваем его из ResultSet
как это:
String field = rs.getString("field");
Затем я передаю эту строку в метод для ее распаковки. Вот где он разваливается.
private String decompressHistory(String historyString) throws SQLException {
StringBuffer buffer = new StringBuffer();
try {
byte[] historyBytes = historyString.substring(4).getBytes();
ByteArrayInputStream bin = new ByteArrayInputStream(historyBytes);
InflaterInputStream in = new InflaterInputStream(bin, new Inflater(true));
int len;
byte[] buf = new byte[1024];
while ((len = in.read(buf)) != -1) {
// buf should be decoded, right?
}
} catch (IOException e) {
e.getStackTrace();
}
return buffer.toString();
}
Не совсем уверен, что здесь происходит, но любые указатели будут оценены!
Вам нужно избавиться от true
в Inflater(true)
, Используйте только Inflater()
, true
заставляет его ожидать необработанных данных. Без true
, это ожидает zlib-обернутые дефляционные данные. РНР gzcompress()
производит zlib-обернутые данные deflate.
Сжатые данные являются двоичными, байтами []. Использование String, текста Unicode не только требует преобразования, но и является дефектным.
Например, это включает преобразование:
byte[] historyBytes = historyString.substring(4).getBytes();
byte[] historyBytes = historyString.substring(4).getBytes("ISO-8859-1");
Первая версия использует кодировку платформы по умолчанию, что делает приложение непереносимым.
Первое, что нужно сделать, это использовать двоичные данные в базе данных как VARBINARY или BLOB.
ImputStream field = rs.getBinaryStream("field");
try (InputStream in = new GZIPInputStream(field)) {
...
}
Или так. Имейте в виду другой ответ.
В итоге ни одно из вышеперечисленных решений не сработало, но оба имеют свои достоинства. Когда мы извлекаем данные из mysql и приводим их к байтам, у нас есть несколько пропущенных символьных байтов (67). Это сделало невозможным распаковку на стороне Java. Что касается ответов выше. Марк прав, что gzcompress () использует zlib, и поэтому вы должны использовать класс Inflater () в Java.
Joop правильно, что преобразование данных является ошибочным. Наш стол был слишком большим, чтобы преобразовать его в varbinary или blob. Тот может решили проблему, но у нас не сработало. Мы закончили тем, что java сделали запрос к нашему приложению PHP, а затем просто распаковали сжатые данные на стороне PHP. Это сработало хорошо. Надеюсь, это полезно для всех, кто сталкивается с этим.