Javascript 节点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');

我试图解析出一个包含Zlib压缩数据序列的数据流。要做到这一点,我需要知道解压需要读取多少数据,以便知道下一次解压需要从哪里继续读取数据

,此值将通过
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();
}