使用C#代码片段压缩的nodejs解压缩string

我使用C#工具收集一些大型的日志信息。 因此,我search了一种方法来压缩这个巨大的string,我发现这个片段做的伎俩:

public static string CompressString(string text) { byte[] buffer = Encoding.UTF8.GetBytes(text); var memoryStream = new MemoryStream(); using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true)) { gZipStream.Write(buffer, 0, buffer.Length); } memoryStream.Position = 0; var compressedData = new byte[memoryStream.Length]; memoryStream.Read(compressedData, 0, compressedData.Length); var gZipBuffer = new byte[compressedData.Length + 4]; Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length); Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4); return Convert.ToBase64String(gZipBuffer); } 

在我的日志logging操作之后,C#工具将这个压缩的string发送到一个node.js REST接口,将其写入数据库。

现在(在我对压缩的天真的理解),我认为我可以简单地使用像nodejs一边的follwoing代码来解压缩它:

 zlib.gunzip(Buffer.from(compressedLogMessage, 'base64'), function(err, uncompressedLogMessage) { if(err) { console.error(err); } else { console.log(uncompressedLogMessage.toString('utf-8')); } }); 

但是我得到的错误:

{错误:在Zlib._handle.onerror错误的头检查(zlib.js:370:17)errno:-3,代码:'Z_DATA_ERROR'}

看来,压缩方法不符合解压缩function。 我希望任何有压缩/解压缩知识的人都可以立即看到这个问题。

我可以改变或改善,使解压缩工作?

非常感谢!

========== UPDATE ===========

看来,消息接收和base64解码工作..使用CompressString("Hello World")结果是:

 // before compression "Hello World" // after compression before base64 encoding new byte[] { 11, 0, 0, 0, 31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 1, 0, 86, 177, 23, 74, 11, 0, 0, 0 } // after base64 encoding CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA= 

而在js节点上:

 // after var buf = Buffer.from('CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=', 'base64'); {"buf":{"type":"Buffer","data":[11,0,0,0,31,139,8,0,0,0,0,0,0,3,243,72,205,201,201,87,8,207,47,202,73,1,0,86,177,23,74,11,0,0,0]}} // after zlib.gunzip(buf, function(err, dezipped) { ... } 

{错误:在Zlib._handle.onerror错误的头检查(zlib.js:370:17)errno:-3,代码:'Z_DATA_ERROR'}

===============更新2 ==================

@ 01binary的回答是正确的! 这是工作的解决scheme:

 function toArrayBuffer(buffer) { var arrayBuffer = new ArrayBuffer(buffer.length); var view = new Uint8Array(arrayBuffer); for (var i = 0; i < buffer.length; ++i) { view[i] = buffer[i]; } return arrayBuffer; } // Hello World (compressed with C#) => CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA= var arrayBuffer = toArrayBuffer(Buffer.from('CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=', 'base64')) var zlib = require('zlib'); zlib.gunzip(Buffer.from(arrayBuffer, 4), function(err, uncompressedMessage) { if(err) { console.log(err) } else { console.log(uncompressedMessage.toString()) // Hello World } }); 

您发现的代码片段似乎会向输出stream的开头写入4个额外的字节,其中包含原始数据的“未压缩”大小。 原作者必须假设接收端的逻辑将读取这4个字节,知道需要分配一个这样大小的缓冲区,并将剩余的stream(+4偏移量)传递给gunzip。

如果您在Node端使用此签名: https : //nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length

…然后传递4的字节偏移量。你的gzipstream的前两个字节应该是{0x1F,0x8b},你可以在你的数组中看到这两个字节从偏移量4开始.zlib头部的一个简单例子可以在这里find:

Zlib压缩不兼容C vs C#实现