代码之家  ›  专栏  ›  技术社区  ›  uriDium

在gzip压缩数据流中创建错误的eof的原因

  •  0
  • uriDium  · 技术社区  · 15 年前

    我们将一个服务器(在Windows上运行在.NET上写入)之间的数据批量传输到一个客户端(用Java运行在Ubuntu上)。数据采用XML格式。在尝试解压流时,Java客户端偶尔会抛出意外的EOF。消息内容总是变化的,并且是用户驱动的。来自客户机的响应也使用gzip压缩。这从未失败过,而且似乎坚如磐石。来自客户端的响应由系统控制。

    是否有可能某些字符排列或某些特殊字符正在创建错误的EOF标记?是否与空白相关?gzip适合压缩XML吗?

    我假设从输入/输出流读取和写入的代码可以工作,因为我们只是偶尔得到这个异常,当我们检查用户数据时,似乎有一些特殊的字符(这就是为什么我问这个问题),例如“@”符号。

    有什么想法吗?

    更新: 请求的实际代码。我认为这不是因为我去了几个网站寻求这个问题的帮助,他们或多或少都有相同的代码。一些网站提到了附加的gzip。与gzip创建多个段有关吗?

    public String receive() throws IOException {
    
        byte[] buffer = new byte[8192];
        ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
    
        do {
            int nrBytes = in.read(buffer);
            if (nrBytes > 0) {
                baos.write(buffer, 0, nrBytes);
            }
        } while (in.available() > 0);
        return compressor.decompress(baos.toByteArray());
    }
       public String decompress(byte[] data) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(data);
    
        try {
            GZIPInputStream inflater = new GZIPInputStream(in); 
            byte[] byteBuffer = new byte[8192];
            int r;
            while((r = inflater.read(byteBuffer)) > 0 ) {
                buffer.write(byteBuffer, 0, r); 
            }
        } catch (IOException e) {
            log.error("Could not decompress stream", e);
            throw e;
        }
        return new String(buffer.toByteArray());
    }
    

    起初,我想我在小溪中读书的方式一定有问题,我想也许我没有正确地循环。然后,我生成了大量要传输的数据,并检查它是否在循环。而且事实上,它们发生的太少,到目前为止还没有被复制,这让我相信这是内容,而不是场景。但在这一点上,我完全困惑了,我所知道的就是代码。

    再次感谢大家。

    更新2:

    按要求.NET代码:

    Dim DataToCompress = Encoding.UTF8.GetBytes(Data)
    Dim CompressedData = Compress(DataToCompress)
    

    将原始数据转换成字节。然后压缩

          Private Function Compress(ByVal Data As Byte()) As Byte()
                Try
                    Using MS = New MemoryStream()
                        Using Compression = New GZipStream(MS, CompressionMode.Compress)
                            Compression.Write(Data, 0, Data.Length)
                            Compression.Flush()
                            Compression.Close()
                            Return MS.ToArray()
                        End Using
                    End Using
                Catch ex As Exception
                    Log.Error("Error trying to compress data", ex)
                    Throw
                End Try
            End Function
    

    更新3:还添加了更多的Java代码。in变量是从socket.getinputstream()返回的inputstream

    3 回复  |  直到 15 年前
        1
  •  1
  •   Jon Skeet    15 年前

    当然 不应该 这要归功于所涉及的数据——流处理二进制数据,所以这不应该产生任何的几率。

    但是,如果没有看到您的代码,就很难确定。我的第一个通话端口是检查你正在使用的任何地方 InputStream.read() -检查您是否正确使用了返回值,而不是假设对 read() 将填充缓冲区。

    如果你能提供一些代码,那会有很大帮助…

        2
  •  0
  •   Thorbjørn Ravn Andersen    15 年前

    我怀疑由于某种原因,数据在进行中被更改,将其视为文本,而不是二进制,因此它可能是转换或代码页更改。

    gzip流如何在两个系统之间传输?

        3
  •  0
  •   user207421    15 年前

    它不是pssible。TCP中的eof作为带外fin段传送,而不是通过数据。