使用 C# 片段压缩的 nodejs 解压缩字符串
Uncompress String with nodejs that was compressed using a C# snippet
我使用 C# 工具收集了一些大型日志信息。因此,我寻找了一种压缩该巨大字符串的方法,并找到了 this 代码段来解决问题:
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);
}
在我的记录操作之后,C# 工具将此压缩字符串发送到 node.js REST 接口,该接口将其写入数据库。
现在(以我对压缩的天真理解)我认为我可以简单地使用类似以下代码的东西 在 nodejs 端 来解压缩它:
zlib.gunzip(Buffer.from(compressedLogMessage, 'base64'), function(err, uncompressedLogMessage) {
if(err) {
console.error(err);
}
else {
console.log(uncompressedLogMessage.toString('utf-8'));
}
});
但我收到错误消息:
{ Error: incorrect header check
at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
好像是压缩方式和解压功能不匹配。我希望任何具有 compression/uncompression 知识的人都可以立即看到问题。
我可以改变或改进什么以使解压缩工作?
非常感谢!
==========更新===========
消息接收和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) { ... }
{ Error: incorrect header check
at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
===============更新 2 ==================
@01binary 回答正确!这是可行的解决方案:
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
}
});
您找到的代码段似乎将 4 个额外字节写入输出流的开头,其中包含原始数据的 "uncompressed" 大小。原作者一定假设接收端的逻辑将要读取这 4 个字节,知道它需要分配那个大小的缓冲区,并将流的其余部分(+4 偏移量)传递给 gunzip。
如果您在节点端使用此签名:
https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length
...然后传递字节偏移量 4。gzip 流的前两个字节应该是 { 0x1F, 0x8b },您可以在数组中看到这两个字节从偏移量 4 开始。一个简单的可以在此处找到 zlib header 的示例:
我使用 C# 工具收集了一些大型日志信息。因此,我寻找了一种压缩该巨大字符串的方法,并找到了 this 代码段来解决问题:
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);
}
在我的记录操作之后,C# 工具将此压缩字符串发送到 node.js REST 接口,该接口将其写入数据库。
现在(以我对压缩的天真理解)我认为我可以简单地使用类似以下代码的东西 在 nodejs 端 来解压缩它:
zlib.gunzip(Buffer.from(compressedLogMessage, 'base64'), function(err, uncompressedLogMessage) {
if(err) {
console.error(err);
}
else {
console.log(uncompressedLogMessage.toString('utf-8'));
}
});
但我收到错误消息:
{ Error: incorrect header check at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
好像是压缩方式和解压功能不匹配。我希望任何具有 compression/uncompression 知识的人都可以立即看到问题。
我可以改变或改进什么以使解压缩工作?
非常感谢!
==========更新===========
消息接收和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) { ... }
{ Error: incorrect header check at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
===============更新 2 ==================
@01binary 回答正确!这是可行的解决方案:
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
}
});
您找到的代码段似乎将 4 个额外字节写入输出流的开头,其中包含原始数据的 "uncompressed" 大小。原作者一定假设接收端的逻辑将要读取这 4 个字节,知道它需要分配那个大小的缓冲区,并将流的其余部分(+4 偏移量)传递给 gunzip。
如果您在节点端使用此签名: https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length
...然后传递字节偏移量 4。gzip 流的前两个字节应该是 { 0x1F, 0x8b },您可以在数组中看到这两个字节从偏移量 4 开始。一个简单的可以在此处找到 zlib header 的示例: