【问题标题】:Sending gzipped data over a network from C# to Java通过网络从 C# 向 Java 发送 gzip 压缩的数据
【发布时间】:2013-11-15 22:21:30
【问题描述】:

我有一个应用程序将从我的 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 编码创建的。

【问题讨论】:

    标签: c# java compression gzip dotnetzip


    【解决方案1】:

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

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

    【讨论】:

    • NetMessage 是从 PC 到平板电脑来回发送的数据消息的包装器。 .getRawMsg() 方法将消息的原始数据作为char[] 返回,这实际上是从 C# 端压缩的。由于GZIPInputStream 需要底层流才能工作,我使用OutputStreamWriter 将char[] 转换为byte[]。这个过程是否以某种方式将原始数据转换为文本?
    • @F.Ali:如果它以char[] 的形式返回数据,则它不是原始数据——它是文本。原始数据是二进制的。 NetMessage 在你的控制之下吗?如果是这样,听起来它需要修复。
    • 是的,看来我需要修改 NetMessage 才能改用 byte[]。谢谢。
    【解决方案2】:

    “BufferedReader 是使用 ASCII 编码创建的。”那么很明显你的程序无法运行。 GZip 压缩数据使用所有字节,因此将其解释为 ASCII 会导致数据丢失。此外,您将字符转换回字节数组而不指定编码,因此使用系统的默认值,这是您程序无法控制的。您必须对两种转换使用相同的编码,并且它必须保留所有位的所有信息,例如使用 iso-latin-1 就可以了。但是最好修复将字节转换为字符并返回字节的缺陷。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多