java - Zlib 压缩在 Java 中使用 Deflate 和 Inflate 类

标签 java compression zlib deflate inflate

我想尝试使用 java.util.zip 中的 Deflate 和 Inflate 类进行 zlib 压缩。

我可以使用 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");

    }
}

最佳答案

你想在这里做什么?您使用一个 InflaterInputStream 来解压缩您的数据,然后您尝试将这个解压缩的数据再次传递给一个 Inflater?使用其中之一,但不能同时使用。

这就是导致您出现异常的原因。

除此之外,还有不少小错误,比如bestsss提到的这些:

  • 您在循环中完成压缩 - 完成后,无法添加更多数据。
  • 您没有检查 deflate 过程产生了多少输出。如果行很长,则可能超过 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"));
    }
}

为了提高效率,用缓冲流包装文件流可能会很有用。如果这对性能至关重要,请对其进行测量。

关于java - Zlib 压缩在 Java 中使用 Deflate 和 Inflate 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6173920/

相关文章:

java - SQLite 数据库的最大插入次数

java - Android - Web 服务器通信

lua - 可以在 corona 中制作 zip 文件吗?

c++ - Zlib解压c++

javascript - 在javascript中解压缩gzip和zlib字符串

java - 将 Image 对象转换为 BufferedImage 对象

java - C 函数指针未在 Android Studio 中编译 : Gives Error "Can' t resolve type F"

python - 在 python 中下载大文件错误 : Compressed file ended before the end-of-stream marker was reached

java - 如何找出固件中嵌入的 GZIP 部分的大小?

c - ZLib 和 memcpy