2012-12-13 4 views
3

Я пытаюсь распаковывать значение, возвращенное с функцией COMPRESS в MySQL:Java/Hibernate: Распаковка сжатого результата

SQLQuery query = session 
      .createSQLQuery("SELECT ID, COMPRESS(TEXT_COL) AS TEXT_COL FROM TABLE WHERE ID IN (1,2,3,...);") 
      .addScalar("ID", Hibernate.INTEGER) 
      .addScalar("TEXT_COL", Hibernate.TEXT); 
List<Object[]> list = query.list(); 
for (Object[] result : list) { 
    String text = decompress(((String) result[1]).getBytes()); 
} 

(...) 
private String decompress(byte[] bs) { 
    InputStream in = new InflaterInputStream(new ByteArrayInputStream(bs)); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    try { 
     byte[] buffer = new byte[8192]; 
     int len; 
     while((len = in.read(buffer))>0) 
      baos.write(buffer, 0, len); 
     return new String(baos.toByteArray(), "UTF-8"); 
    } catch (IOException e) { 
     throw new AssertionError(e); 
    } 
} 

И я получаю java.lang.AssertionError: java.util.zip.ZipException : некорректная проверка заголовка

Каков способ декомпрессии такого результата mysql или что не так с моим кодом?

Заранее спасибо, Diego.

EDIT: Благодаря Joni за предложения, я, наконец, изменил код

SQLQuery query = session 
      .createSQLQuery("SELECT ID, COMPRESS(TEXT_COL) AS TEXT_COL FROM TABLE WHERE ID IN (1,2,3,...);") 
      .addScalar("ID", Hibernate.INTEGER) 
      .addScalar("TEXT_COL", Hibernate.BINARY); 
List<Object[]> list = query.list(); 
for (Object[] result : list) { 
    String text = decompress(((byte[]) result[1])); 
} 

(...) 
private String decompress(byte[] bs) { 
    InputStream in = new InflaterInputStream(new ByteArrayInputStream(bs, 4, bs.length-4)); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    try { 
     byte[] buffer = new byte[8192]; 
     int len; 
     while((len = in.read(buffer))>0) 
      baos.write(buffer, 0, len); 
     return new String(baos.toByteArray(), "UTF-8"); 
    } catch (IOException e) { 
     throw new AssertionError(e); 
    } 
} 

ответ

5

Вы должны пропустить 4 байта в начале потока:

InputStream in = new InflaterInputStream(
        new ByteArrayInputStream(bs, 4, bs.length-4)); 

Этот потому что функция COMPRESS возвращает строку, в которой первые четыре байта дают длину сжатых данных, а следующие байты являются фактическими сжатыми данными.

Кроме того, вы должны попытаться найти способ получить результат непосредственно в виде байтов. Сжатый результат - двоичные данные и, вероятно, не может быть безопасно преобразован в строку.

+0

Спасибо, я был на треке: я видел на форуме php вопрос о первых 4 байтах. –

Смежные вопросы