我有一个应用程序将从我的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编码创建。
答案 0 :(得分:2)
因为数据是由BufferedReader读入的,所以我最初必须从char []转换为byte []:
这是巨大的问题。你压缩了数据。这是任意的二进制数据。您应该绝对不将其视为文本。我不清楚NetMessage
是什么,但基本上你需要访问你通过网络发送的原始二进制数据 - 否则你没有机会解压缩它。
答案 1 :(得分:2)
“BufferedReader是使用ASCII编码创建的。”然后很明显,你的程序无法正常工作。 GZip压缩数据使用所有字节的字节,因此将其解释为ASCII会导致数据丢失。此外,您将字符转换回字节数组而不指定编码,因此使用系统的默认值,这超出了程序的控制范围。您必须对两个转换使用相同的编码,并且必须保留所有位的所有信息,例如使用iso-latin-1可以完成这项工作。但是,修复将字节转换为字符并返回字节的缺陷要好得多。