膨胀解压缩:ZLIB输入流的意外结束

时间:2014-08-06 08:57:45

标签: java

我正在尝试用Java实现一个侦听器,它将侦听System.in,读取已使用Deflate压缩的数据,解压缩数据,然后将其写入System.out。

我想实时处理流式传输到System.in的数据,因此我需要在解压缩数据时保持套接字连接和输入流打开。逐行读出解压缩数据也很重要。我已经实现了以下代码来从压缩流中读取并写入新的输出流:

    InputStream inputStream = System.in;
    InflaterInputStream inflaterInputStream = new InflaterInputStream(inputStream);

    BufferedReader reader = new BufferedReader(new InputStreamReader(inflaterInputStream));

    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

我正在使用以下Linux命令测试代码:

    cat file_with_compressed_data.txt | java Inflate > outputFile.txt

Inflate是我的System.in监听器类。但是,运行此命令时,我收到以下异常:

    Exception in thread "main" java.io.EOFException: Unexpected end of ZLIB input stream
        at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:223)
        at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:158)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
        at java.io.InputStreamReader.read(InputStreamReader.java:167)
        at java.io.BufferedReader.fill(BufferedReader.java:136)
        at java.io.BufferedReader.readLine(BufferedReader.java:299)
        at java.io.BufferedReader.readLine(BufferedReader.java:362)
        at Inflate.main(Inflate.java:30)

解压缩似乎正在起作用,因为outputFile.txt包含大多数原始的解压缩数据。但是,outputFile.txt中缺少原始文件中的一些行。

我无法理解为什么会抛出此异常。有没有其他方法可以实时解压缩Deflated数据而不关闭我的输入流?

我的java版本是:

    java version "1.6.0_33"
    Java(TM) SE Runtime Environment (build 1.6.0_33-b03)
    Java HotSpot(TM) 64-bit Server VM (build 20.8-b03, mixed mode)

可以使用以下方法创建压缩文件:

    DeflaterOutputStream out = new DeflaterOutputStream(System.out);
    int c;
    while ((c = System.in.read()) != -1) {
        out.write(c);
    }
    out.flush();
    out.close();

1 个答案:

答案 0 :(得分:0)

经过一番调查后,我找到了问题的解决方案。我看起来好像是导致问题的BufferedReader,虽然我必须承认我仍然不明白为什么。我用StringBuilder替换了BufferedReader来生成:

InputStream inputStream = System.in;
InflaterInputStream inflaterInputStream =  new InflaterInputStream(inputStream);

StringBuilder toReturn = new StringBuilder();
int c;
while ((c = inflaterInputStream.read()) != -1) {
    toReturn.append((char) c);
    if ((char) c == '\n') {
        System.out.println(toReturn.toString());
        toReturn.setLength(0);
    }
}