2011-05-30 20 views
8

zlib圧縮のためにjava.util.zipのDeflateクラスとInflateクラスを使用したいと考えています。JavaのDeflateクラスとInflateクラスを使用したZlib圧縮

私はデフレートを使用してコードを圧縮することができる午前、しかし、私はこのエラーが生じています解凍中 - ここ

Exception in thread "main" java.util.zip.DataFormatException: unknown compression method 
    at java.util.zip.Inflater.inflateBytes(Native Method) 
    at java.util.zip.Inflater.inflate(Inflater.java:238) 
    at java.util.zip.Inflater.inflate(Inflater.java:256) 
    at zlibCompression.main(zlibCompression.java:53) 

はこれまでのところ、私のコードです -

import java.util.zip.*; 
import java.io.*; 

public class zlibCompression { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) throws IOException, DataFormatException { 
     // TODO Auto-generated method stub 

     String fname = "book1"; 
     FileReader infile = new FileReader(fname); 
     BufferedReader in = new BufferedReader(infile); 

     FileOutputStream out = new FileOutputStream("book1out.dfl"); 
     //BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename)); 

     Deflater compress = new Deflater(); 
     Inflater decompress = new Inflater(); 

     String readFile = in.readLine(); 
     byte[] bx = readFile.getBytes(); 

     while(readFile!=null){ 
      byte[] input = readFile.getBytes(); 
      byte[] compressedData = new byte[1024]; 
      compress.setInput(input); 
      compress.finish(); 
      int compressLength = compress.deflate(compressedData, 0, compressedData.length); 
      //System.out.println(compressedData); 
      out.write(compressedData, 0, compressLength); 
      readFile = in.readLine(); 
     } 

     File abc = new File("book1out.dfl"); 
     InputStream is = new FileInputStream("book1out.dfl"); 

     InflaterInputStream infl = new InflaterInputStream(new FileInputStream("book1out.dfl"), new Inflater()); 
     FileOutputStream outFile = new FileOutputStream("decompressed.txt"); 

     byte[] b = new byte[1024]; 
     while(true){ 

      int a = infl.read(b,0,1024); 
      if(a==0) 
       break; 

      decompress.setInput(b); 
      byte[] fresult = new byte[1024]; 
      //decompress.in 
      int resLength = decompress.inflate(fresult); 
      //outFile.write(b,0,1); 
      //String outt = new String(fresult, 0, resLength); 
      //System.out.println(outt); 
     } 

     System.out.println("complete"); 

    } 
} 
+0

その宿題ですか? 1つの間違いはあまりにも早く呼び出しを終了している、もう1つはsetInput w/oの長さを使用しており、もう1つは収縮プロセスが1024より多くのデータを返したかどうかを確認していません。 – bestsss

答えて

25

あなたが何をしようとしていますここでやる?データを解凍するInflaterInputStreamを使用し、この解凍されたデータを再度Inflaterに渡そうとしますか?いずれか1つを使用しますが、両方を使用することはできません。

ここで例外が発生しています。 - 終了後に、これ以上のデータを追加することができます

  • あなたは、ループ内の圧縮を終える:

    は、これに加えて、bestsssが言及したこれらのような、非常にいくつかのマイナーなエラーがあります。

  • デフレートプロセスで生成される出力の量はチェックしません。長い行がある場合は、1024バイトを超える可能性があります。
  • 長さをaに設定せずに、Inflaterに入力を設定します。

私が見つけたいくつかの詳細:

  • あなたが書いた後(と同じファイルから読み込む前に)あなたのFileOutputStreamを閉じないし。
  • readLine()を使用してテキスト行を読み込みますが、改行文字列をもう一度追加しないでください。つまり、圧縮解除されたファイルには改行はありません。
  • 必要に応じて、バイトからストリング、およびバイトに変換し直します。
  • 後で使用しない変数を作成します。

私はあなたのプログラムを修正しようとしません。 DeflaterOutputStreamとInflaterInputStreamを使用して、あなたが望むと思うことを行う簡単な方法があります。 (また、代わりにJZlibのZInputStreamとZOutputStreamを使用することができます。)

import java.util.zip.*; 
import java.io.*; 

/** 
* Example program to demonstrate how to use zlib compression with 
* Java. 
* Inspired by http://stackoverflow.com/q/6173920/600500. 
*/ 
public class ZlibCompression { 

    /** 
    * Compresses a file with zlib compression. 
    */ 
    public static void compressFile(File raw, File compressed) 
     throws IOException 
    { 
     InputStream in = new FileInputStream(raw); 
     OutputStream out = 
      new DeflaterOutputStream(new FileOutputStream(compressed)); 
     shovelInToOut(in, out); 
     in.close(); 
     out.close(); 
    } 

    /** 
    * Decompresses a zlib compressed file. 
    */ 
    public static void decompressFile(File compressed, File raw) 
     throws IOException 
    { 
     InputStream in = 
      new InflaterInputStream(new FileInputStream(compressed)); 
     OutputStream out = new FileOutputStream(raw); 
     shovelInToOut(in, out); 
     in.close(); 
     out.close(); 
    } 

    /** 
    * Shovels all data from an input stream to an output stream. 
    */ 
    private static void shovelInToOut(InputStream in, OutputStream out) 
     throws IOException 
    { 
     byte[] buffer = new byte[1000]; 
     int len; 
     while((len = in.read(buffer)) > 0) { 
      out.write(buffer, 0, len); 
     } 
    } 


    /** 
    * Main method to test it all. 
    */ 
    public static void main(String[] args) throws IOException, DataFormatException { 
     File compressed = new File("book1out.dfl"); 
     compressFile(new File("book1"), compressed); 
     decompressFile(compressed, new File("decompressed.txt")); 
    } 
} 

より効率のために、バッファリングされたストリームとファイルストリームをラップするために役に立つかもしれません。パフォーマンスが重要な場合は、測定してください。

+0

これはzlib用です。私はzlibファイルを解凍しようとしますが、私は '未知の圧縮方法'エラーを受け取ります。私がhttp://docs.oracle.com/javase/1.4.2/docs/api/java/util/zip/package-summary.htmlを見ると、 'Inflater'がzlibについて言及していますが、あなたは' InflaterInputStream'を使用します。デフレート圧縮方法について述べる。 ファイルは https://dl.dropboxusercontent.com/u/17630770/temp/pc_oj_simple_AnimTake1_11です。icecache.zip – clankill3r

+0

InflaterInputStreamは(Inflaterパラメータなしのコンストラクタを使用する場合) '新しいInflater()'を使用します。そしてこのコンストラクタは 'nowrap = false'を使います。これはzlib圧縮を意味します。 (私はあなたのファイルをチェックしていませんでした) –

4

Paŭlo Ebermannのコードをさらにtry-with-resourcesを使用することによって改善することができる。

import java.util.Scanner; 
import java.util.zip.*; 
import java.io.*; 

public class ZLibCompression 
{ 
    public static void compress(File raw, File compressed) throws IOException 
    { 
     try (InputStream inputStream = new FileInputStream(raw); 
      OutputStream outputStream = new DeflaterOutputStream(new FileOutputStream(compressed))) 
     { 
      copy(inputStream, outputStream); 
     } 
    } 

    public static void decompress(File compressed, File raw) 
      throws IOException 
    { 
     try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed)); 
      OutputStream outputStream = new FileOutputStream(raw)) 
     { 
      copy(inputStream, outputStream); 
     } 
    } 

    public static String decompress(File compressed) throws IOException 
    { 
     try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed))) 
     { 
      return toString(inputStream); 
     } 
    } 

    private static String toString(InputStream inputStream) 
    { 
     try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A")) 
     { 
      return scanner.hasNext() ? scanner.next() : ""; 
     } 
    } 

    private static void copy(InputStream inputStream, OutputStream outputStream) 
      throws IOException 
    { 
     byte[] buffer = new byte[1000]; 
     int length; 

     while ((length = inputStream.read(buffer)) > 0) 
     { 
      outputStream.write(buffer, 0, length); 
     } 
    } 
} 
+0

スキャナの目標は何ですか?ストリームの最初の行を取得するだけですか? –

+1

@PaŭloEbermann: これはストリーム全体を一度に読むためのトリックです – BullyWiiPlaza

関連する問題