解压缩,转换和压缩回nodejs中的大文件

时间:2019-08-30 07:24:47

标签: javascript node.js file-io zlib

我有相当大的压缩后的rdf文件(压缩后为30Gb,压缩后为约300Gb),我需要逐行处理并将gzip压缩回另一个文件。因此,这就是我目前拥有的内容(测试中的file压缩了〜150Mb)

const fs = require('fs');
const zlib = require('zlib');
const readline = require('readline');

const readStream = fs.createReadStream('21million.rdf.gz').pipe(zlib.createGunzip());
const writeStream = fs.createWriteStream("21million.rdf");
const gzipStream = zlib.createGzip();

gzipStream.pipe(writeStream);


const rl = readline.createInterface({
    input: readStream,
    output: gzipStream,
});

rl.on('line', (line) => {
    gzipStream.write(`${line.toUpperCase()}\n`);
});

rl.on('close', () => {
    console.log('done');
    gzipStream.end();
});

问题在于我收到FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

问题是-如何设置它,以免出现OOM问题?

PS。我知道它可以用sed,awk,pert等完成,但我需要在js中完成。

1 个答案:

答案 0 :(得分:0)

这是由于Node.js处理Streams的方式所致。也称为backpressuring。当Readable流提供的数据快于Writer消耗的速度时,就会发生这种情况,这会导致内存使用量增加,因为必须将数据保留在内存中,直到整个过程完成为止。

解决此问题的一种方法是使用Transform流,该流处理通过管道进行的数据转换。

以下代码应该完成您要实现的目标:

const stream = require('stream');

const transformStream = new stream.Transform({
    writableObjectMode: true,
    transform: (chunk, encoding, callback) => {
        const chunkText = chunk.toString(encoding);
        const modifiedChunkText = chunkText.toUpperCase(); // apply modifications to the text
        callback(false, Buffer.from(modifiedChunkText, encoding));
    }
});

readStream // reads from 21million.rdf.gz
    .pipe(transformStream) // transforms data
    .pipe(gzipStream) // writes to output file
    .on('finish', () => {
        console.log('done');
    });