13

zlib 圧縮のために java.util.zip の Deflate および Inflate クラスを使用しようとしています。

Deflate を使用してコードを圧縮することはできますが、解凍中にこのエラーが発生します -

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");

    }
}
4

2 に答える 2

31

ここで何をしようとしていますか?データを解凍する InflaterInputStream を使用してから、この解凍されたデータを Inflater に再度渡そうとしますか? 両方ではなく、どちらか一方を使用してください。

これがあなたの例外の原因です。

これに加えて、bestsss で言及されているような、いくつかの小さなエラーがあります。

  • ループ内で圧縮を終了します。終了後、データを追加することはできません。
  • deflate プロセスが生成する出力の量はチェックしません。行が長い場合は、1024 バイトを超える可能性があります。
  • length も設定せずに、入力を Inflater に設定しaます。

私が見つけたいくつかのより:

  • 書き込み後 (および同じファイルから読み取る前) に 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"));
    }
}

効率を高めるために、ファイル ストリームをバッファリングされたストリームでラップすると便利な場合があります。これがパフォーマンス上重要な場合は、測定してください。

于 2011-06-15T23:46:26.777 に答える