Javascript 节点zlib模块充气,是否知道读取了多少数据(总英寸)?
我试图解析出一个包含Zlib压缩数据序列的数据流。要做到这一点,我需要知道解压需要读取多少数据,以便知道下一次解压需要从哪里继续读取数据 ,此值将通过Javascript 节点zlib模块充气,是否知道读取了多少数据(总英寸)?,javascript,node.js,zlib,node-modules,Javascript,Node.js,Zlib,Node Modules,我试图解析出一个包含Zlib压缩数据序列的数据流。要做到这一点,我需要知道解压需要读取多少数据,以便知道下一次解压需要从哪里继续读取数据 ,此值将通过z_流结构中的total_成员公开 我可以使用zlib的JavaScript端口实现这一点,但我更愿意使用,因为它可以避免额外的依赖性,并且具有异步支持 下面是一个代码示例,它显示了实际中的这一困境 'use strict'; const zlib = require('zlib'); const pako = require('pako');
z_流
结构中的total_成员公开
我可以使用zlib的JavaScript端口实现这一点,但我更愿意使用,因为它可以避免额外的依赖性,并且具有异步支持
下面是一个代码示例,它显示了实际中的这一困境
'use strict';
const zlib = require('zlib');
const pako = require('pako');
const str = 'testing';
const extra = new Uint8Array([2, 4, 6, 8, 10]);
const data = new Uint8Array(zlib.deflateSync(str));
const dataExtra = new Uint8Array(data.length + extra.length);
dataExtra.set(data);
dataExtra.set(extra, data.length);
console.log(data);
console.log(dataExtra);
// Inflate with pako module.
// Accessing the amount read is easy.
const pakoInflate = new pako.Inflate();
pakoInflate.push(dataExtra, true);
const pakoInflated = new Buffer(pakoInflate.result.buffer);
console.log(pakoInflated, pakoInflated.toString());
console.log(pakoInflate.strm.total_in);
// Inflate with zlib module.
// Any way to know how much data was actually read?
const zlibInflated = zlib.inflateSync(new Buffer(dataExtra));
console.log(zlibInflated, zlibInflated.toString());
样本输出(15是读取的压缩数据的长度):
Uint8Array[120156,43,73,45,46201204,75,7,0,12,30,2255]
Uint8Array[120156,43,73,45,46201204,75,7,0,12,30,2255,2,4,6,8,10]
“测试”
15
“测试”
似乎zlib.inflate*
方法不会公开此信息,但是否有其他方法可以做到这一点?也许是zlib
模块的其他方法之一启用了此功能?或者这些信息对JavaScript代码完全不可用?Node以前没有公开这个特性,所以我提交了一些请求来添加它
从节点8.1开始,现在可以使用本机zlib
模块访问此信息。Zlib引擎现在使属性可用,方便的方法现在可以通过传递来访问它
工作示例:
从技术上讲,在较旧的节点版本中也可以做到这一点,尽管它需要对私有属性进行一些猴子补丁。您还必须直接使用流对象
Monkey修补程序示例(对于旧节点版本):
它看起来并没有以任何方式暴露出来。这是接口中的一个缺陷。您应该请求类似python的未使用的_数据
,这是解决此问题的正确方法total_in
不是这样做的,因为该计数器原则上可能会因大输入而溢出。
Uint8Array [ 120, 156, 43, 73, 45, 46, 201, 204, 75, 7, 0, 12, 30, 2, 255 ]
Uint8Array [ 120, 156, 43, 73, 45, 46, 201, 204, 75, 7, 0, 12, 30, 2, 255, 2, 4, 6, 8, 10 ]
<Buffer 74 65 73 74 69 6e 67> 'testing'
15
<Buffer 74 65 73 74 69 6e 67> 'testing'
'use strict';
const zlib = require('zlib');
const str = 'abcdefgh'.repeat(2);
const data = new Uint8Array(zlib.deflateSync(str));
const extra = new Uint8Array([2, 4, 6, 8, 10]);
const dataExtra = new Uint8Array(data.length + extra.length);
dataExtra.set(data);
dataExtra.set(extra, data.length);
testSync();
function testSync() {
const info = zlib.inflateSync(dataExtra, {info: true});
console.log('Sync:');
console.log(str, '==', info.buffer.toString());
console.log(data.length, '==', info.engine.bytesRead);
console.log();
testAsync();
}
function testAsync() {
zlib.inflate(dataExtra, {info: true}, (err, info) => {
console.log('Async:');
console.log(str, '==', info.buffer.toString());
console.log(data.length, '==', info.engine.bytesRead);
console.log();
testStream();
});
}
function testStream() {
let buffer = new Buffer(0);
const inf = new zlib.Inflate();
inf.on('data', (d) => {
buffer = Buffer.concat([buffer, d]);
});
inf.on('end', () => {
console.log('Stream:');
console.log(str, '==', buffer.toString());
console.log(data.length, '==', inf.bytesRead);
console.log();
});
inf.write(dataExtra);
inf.end();
}
'use strict';
const zlib = require('zlib');
const str = 'abcdefgh'.repeat(2);
const data = new Uint8Array(zlib.deflateSync(str));
const extra = new Uint8Array([2, 4, 6, 8, 10]);
const dataExtra = new Uint8Array(data.length + extra.length);
dataExtra.set(data);
dataExtra.set(extra, data.length);
class Inflate extends zlib.Inflate {
constructor(opts, mode) {
super(opts, mode);
if (!('bytesRead' in this)) {
const self = this;
this.bytesRead = 0;
const handle = this._handle;
const writeSync = handle.writeSync;
handle.writeSync = function() {
const availInBefore = arguments[3];
const r = writeSync.apply(this, arguments);
self.bytesRead += availInBefore - r[0];
return r;
};
const write = handle.write;
handle.write = function() {
const availInBefore = arguments[3];
const r = write.apply(this, arguments);
let callback;
const cb = function() {
self.bytesRead += availInBefore - arguments[0];
callback.apply(r, arguments);
};
Object.defineProperty(r, 'callback', {
configurable: true,
enumerable: true,
get: () => {
return cb;
},
set: (value) => {
callback = value;
}
});
return r;
};
}
}
}
testSync();
function testSync() {
const inf = new Inflate();
const buffer = inf._processChunk(dataExtra, inf._finishFlushFlag);
inf.end();
console.log('Sync:');
console.log(str, '==', buffer.toString());
console.log(data.length, '==', inf.bytesRead);
console.log();
testAsync();
}
function testAsync() {
let buffer = new Buffer(0);
const inf = new Inflate();
inf.on('data', (d) => {
buffer = Buffer.concat([buffer, d]);
});
inf.on('end', () => {
console.log('Async:');
console.log(str, '==', buffer.toString());
console.log(data.length, '==', inf.bytesRead);
console.log();
});
inf.write(dataExtra);
inf.end();
}