通过网络将gzip数据从C#发送到Java

时间:2013-11-15 22:21:31

标签: c# java compression gzip dotnetzip

我有一个应用程序将从我的PC上的数据源(例如,Excel或Access)收集的数据发送到Android平板电脑上的接收应用程序。我处于测试阶段,在数据发送之前压缩数据,然后在收到数据后对其进行解压缩。我正在使用GZIP,在C#端使用DotNetZip,在Java端使用内置的GZIPInputStream类。

我遇到问题让它正常工作。当我在一侧进行测试(压缩和解压缩以查看数据是否保持完整)时,一切都很好。它适用于C#和Java。但是当我到达发送和接收的数据时,我遇到了这个问题:“未知格式(幻数ef1f)。”我已经看过其他SO帖子已经讨论过,但答案似乎没有帮助。

以下是我在C#端压缩的代码:

public void compressData() {
    byte[] buffer = Ionic.Zlib.GZipStream.CompressBuffer(this.RawStreamData.ToArray());
    this.RawStreamData = new MemoryStream(buffer);
}

这是我用来在Java端解压缩的代码。因为数据是由BufferedReader读入的,所以我最初必须从char []转换为byte []:

public NetMessage decompressMsg(NetMessage nMsg) throws IOException {
    ByteArrayOutputStream baOut = new ByteArrayOutputStream();
    OutputStreamWriter osWriter = new OutputStreamWriter(baOut);
    osWriter.write(nMsg.getRawMsg());  //.getRawMsg() returns a char[] of the raw data
    osWriter.close();
    ByteArrayInputStream baIn = new ByteArrayInputStream(baOut.toByteArray());
    GZIPInputStream gzIn = new GZIPInputStream(baIn);
    byte[] buffer = new byte[128];
    int nReadBytes = gzIn.read(buffer);
    String sDecompMsg = new String(buffer);

    while (nReadBytes > -1) {
        buffer = new byte[128];
        nReadBytes = gzInput.read(buffer);
        String sTemp = new String(buffer);
        sDecompMsg += sTemp;
    }

    nMsg.setRawMsg(sDecompMsg.toCharArray());

    return nMsg;
}

当我尝试构造GZIPInputStream时抛出异常。我已经知道我从生成的解压缩缓冲区重构消息的方式是错误的(仅在Java端测试),但这是我需要首先达到的问题! :) 任何帮助,将不胜感激。我怀疑它可能与压缩级别设置有关;在C#中我使用的是默认值,但AFAIK在Java端没有这样的设置。 BufferedReader使用ASCII编码创建。

2 个答案:

答案 0 :(得分:2)

  

因为数据是由BufferedReader读入的,所以我最初必须从char []转换为byte []:

这是巨大的问题。你压缩了数据。这是任意的二进制数据。您应该绝对不将其视为文本。我不清楚NetMessage是什么,但基本上你需要访问你通过网络发送的原始二进制数据 - 否则你没有机会解压缩它。

答案 1 :(得分:2)

“BufferedReader是使用ASCII编码创建的。”然后很明显,你的程序无法正常工作。 GZip压缩数据使用所有字节的字节,因此将其解释为ASCII会导致数据丢失。此外,您将字符转换回字节数组而不指定编码,因此使用系统的默认值,这超出了程序的控制范围。您必须对两个转换使用相同的编码,并且必须保留所有位的所有信息,例如使用iso-latin-1可以完成这项工作。但是,修复将字节转换为字符并返回字节的缺陷要好得多。