2013-05-03 47 views
31

次のコードを使用して文字列データを圧縮および解凍していますが、私が直面している問題は簡単にエラーなく圧縮されますが、スレッド内Javaの文字列データの圧縮と解凍

例外は、「メイン」にjava.io.IOException:gzip形式でない

public static void main(String[] args) throws Exception { 
     String string = "I am what I am hhhhhhhhhhhhhhhhhhhhhhhhhhhhh" 
       + "bjggujhhhhhhhhh" 
       + "rggggggggggggggggggggggggg" 
       + "esfffffffffffffffffffffffffffffff" 
       + "esffffffffffffffffffffffffffffffff" 
       + "esfekfgy enter code here`etd`enter code here wdd" 
       + "heljwidgutwdbwdq8d" 
       + "skdfgysrdsdnjsvfyekbdsgcu" 
       +"jbujsbjvugsduddbdj"; 

     System.out.println("after compress:"); 
     String compressed = compress(string); 
     System.out.println(compressed); 
     System.out.println("after decompress:"); 
     String decomp = decompress(compressed); 
     System.out.println(decomp); 
    } 


    public static String compress(String str) throws Exception { 
     if (str == null || str.length() == 0) { 
      return str; 
     } 
     System.out.println("String length : " + str.length()); 
     ByteArrayOutputStream obj=new ByteArrayOutputStream(); 
     GZIPOutputStream gzip = new GZIPOutputStream(obj); 
     gzip.write(str.getBytes("UTF-8")); 
     gzip.close(); 
     String outStr = obj.toString("UTF-8"); 
     System.out.println("Output String length : " + outStr.length()); 
     return outStr; 
    } 

     public static String decompress(String str) throws Exception { 
     if (str == null || str.length() == 0) { 
      return str; 
     } 
     System.out.println("Input String length : " + str.length()); 
     GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(str.getBytes("UTF-8"))); 
     BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8")); 
     String outStr = ""; 
     String line; 
     while ((line=bf.readLine())!=null) { 
      outStr += line; 
     } 
     System.out.println("Output String lenght : " + outStr.length()); 
     return outStr; 
    } 

はまだこの問題を解決する方法を見つけ出すことができませんでした! objは任意のバイナリデータを含む

String outStr = obj.toString("UTF-8"); 

バイト配列:

+1

あなたの努力を高く評価し、実行中のプログラムで質問を投稿していただきありがとうございます。 –

答えて

30

これは、あなたのByteArrayOutputStreamから取得し、あなたのGZIPInputStreamを構築するためにあなたのByteArrayInputStreamでそのようにそれを使用することができたbyte[]を送るため

String outStr = obj.toString("UTF-8"); 

です。以下は、コード内で行う必要のある変更です。

byte[] compressed = compress(string); //In the main method 

public static byte[] compress(String str) throws Exception { 
    ... 
    ... 
    return obj.toByteArray(); 
} 

public static String decompress(byte[] bytes) throws Exception { 
    ... 
    GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); 
    ... 
} 
+9

また、文字列を変更するのではなく、StringBuilderを使用することを検討してください。文字列が不変で、文字列プール内にスペースが無駄になるからです。(インクの川がこぼれ落ちました) – fornarat

7

問題は、この行です。任意のバイナリデータをUTF-8のように "デコード"することはできません。試してみると、バイトに "エンコード"することができないStringを取得します。または、少なくとも、あなたが得るバイトはあなたが始めたものとは違うでしょう...彼らがもはや有効なGZIPストリームではないほどです。

この修正は、バイト配列の内容をそのまま保存または送信することです。それを文字列に変換しようとしないでください。バイナリデータであり、テキストではありません。

+0

しかし、圧縮されたデータをテキストとして保存したい場合、これをどのように達成できますか? – perrohunter

+3

base64などのバイナリ形式のテキストエンコーディングを使用します。 –

11

あなたがネットワーク経由でzip形式のコンテンツを転送したり、テキストとして保存する必要がある場合は、Base64で文字列をバイト配列に変換する(たとえば、ApacheのコモンズのコーデックをBase64など)をBase64エンコーダを使用する必要があり、およびデコードリモートクライアントの文字列をバイト配列に戻します。 例を見つけたのはUse Zip Stream and Base64 Encoder to Compress Large String Data

+0

結果の文字列が必要な場合の良い例 – demon101

+0

最も簡単な例gzippingのために私はまだ出てきました。 –

17

上記の回答は私たちの問題を解決しますが、それに加えてです。 圧縮されていない( "zip形式ではない")byte []を解凍しようとしている場合。 「GZIP形式ではありません」例外メッセージが表示されます。

私たちのクラスに追加コードを追加できることを解決するために。

public static boolean isCompressed(final byte[] compressed) { 
    return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)); 
} 

圧縮/解凍と私の完全な圧縮クラスは次のようになります。あなたがバイナリデータを文字列に変換することはできません

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.zip.GZIPInputStream; 
import java.util.zip.GZIPOutputStream; 

public class GZIPCompression { 
    public static byte[] compress(final String str) throws IOException { 
    if ((str == null) || (str.length() == 0)) { 
     return null; 
    } 
    ByteArrayOutputStream obj = new ByteArrayOutputStream(); 
    GZIPOutputStream gzip = new GZIPOutputStream(obj); 
    gzip.write(str.getBytes("UTF-8")); 
    gzip.flush(); 
    gzip.close(); 
    return obj.toByteArray(); 
    } 

    public static String decompress(final byte[] compressed) throws IOException { 
    final StringBuilder outStr = new StringBuilder(); 
    if ((compressed == null) || (compressed.length == 0)) { 
     return ""; 
    } 
    if (isCompressed(compressed)) { 
     final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed)); 
     final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, "UTF-8")); 

     String line; 
     while ((line = bufferedReader.readLine()) != null) { 
     outStr.append(line); 
     } 
    } else { 
     outStr.append(compressed); 
    } 
    return outStr.toString(); 
    } 

    public static boolean isCompressed(final byte[] compressed) { 
    return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)); 
    } 
} 
+0

非常にいいです。 'gzip.close();'の前に 'gzip.flush();'の呼び出しがありません。 – isapir

+2

このコードを確認していただきありがとうございます。 –

+0

私はあなたのコードを使用して、私はあなたの解凍方法では、破断線のために少し修正を追加:「しばらく(!(ライン=はBufferedReader.readLine())= NULL){ \t \t \t \t outStr.append(ライン); \t \t \t \t outStr.append(System.getProperty( "line.separator")); \t \t \t} –

0

正しい圧縮と解凍の別の例を見て:

@Slf4j 
public class GZIPCompression { 
    public static byte[] compress(final String stringToCompress) { 
     if (isNull(stringToCompress) || stringToCompress.length() == 0) { 
      return null; 
     } 

     try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      final GZIPOutputStream gzipOutput = new GZIPOutputStream(baos)) { 
      gzipOutput.write(stringToCompress.getBytes(UTF_8)); 
      gzipOutput.finish(); 
      return baos.toByteArray(); 
     } catch (IOException e) { 
      throw new UncheckedIOException("Error while compression!", e); 
     } 
    } 

    public static String decompress(final byte[] compressed) { 
     if (isNull(compressed) || compressed.length == 0) { 
      return null; 
     } 

     try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressed)); 
      final StringWriter stringWriter = new StringWriter()) { 
      IOUtils.copy(gzipInput, stringWriter, UTF_8); 
      return stringWriter.toString(); 
     } catch (IOException e) { 
      throw new UncheckedIOException("Error while decompression!", e); 
     } 
    } 
} 
関連する問題