问题
I have an application that sends data gathered from a data source on my PC (say, Excel or Access) to a receiving app on an Android tablet. I am in the testing stage of compressing the data before it is sent and then decompressing it after it is received. I'm using GZIP for this, with DotNetZip on the C# side and the built-in GZIPInputStream class on the Java side.
I'm having issues getting it to work properly. When I do a test just on one side (compressing and decompressing to see if the data remains intact), everything is fine. It works on both C# and Java. But when I get to the point of the data being sent over and received, I run into this issue: "unknown format (magic number ef1f)." I've seen other SO posts where this has been discussed but the answers don't seem to help.
Here is the code I am using to compress on the C# side:
public void compressData() {
byte[] buffer = Ionic.Zlib.GZipStream.CompressBuffer(this.RawStreamData.ToArray());
this.RawStreamData = new MemoryStream(buffer);
}
And here is the code I am using to decompress on the Java side. Because the data is read in by a BufferedReader, I have to convert from char[] to byte[] initially:
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;
}
It throws the exception when I try to construct the GZIPInputStream. I already know the way I am reconstructing the message from the resulting decompressed buffer is wrong (from testing on the Java side only), but that is a problem I need to reach first! :) Any help would be appreciated. I suspect it might have something to do with the compression level settings; in C# I am using the default, but AFAIK there is no such setting on the Java side. The BufferedReader is created with an ASCII encoding.
回答1:
Because the data is read in by a BufferedReader, I have to convert from char[] to byte[] initially:
That's a huge problem. You've compressed the data. It's arbitrary binary data. You should absolutely not be treating it as text. It's not clear to me what NetMessage
is, but basically you'll need to get access to the raw binary data you're sending over the network - otherwise you've got no chance of decompressing it.
回答2:
“The BufferedReader is created with an ASCII encoding.” Then it’s obvious that your program can’t work. GZip compressed data use all bit of the bytes so interpreting it as ASCII causes data loss. Further, you convert the chars back to a byte array without specifying an encoding so the system’s default is used which is beyond the control of you program. You have to use the same encoding for both conversions and it must retain all informations of all bits, e.g. using iso-latin-1 would do the job. But it’d be far better to fix that flaw of converting bytes to chars and back to bytes.
来源:https://stackoverflow.com/questions/20011650/sending-gzipped-data-over-a-network-from-c-sharp-to-java