节点流缓冲区在console.log与process.stdout.write中

时间:2016-02-17 10:57:21

标签: node.js character-encoding buffer

使用 NodeJS v5.6 我创建了一个名为read-stream.js的文件:

const
    fs = require('fs'),
    stream = fs.createReadStream(process.argv[2]);

stream.on('data', function(chunk) {
    process.stdout.write(chunk);
});

stream.on('error', function(err) {
    process.stderr.write("ERROR: " + err.message + "\n");
});

和一个名为target.txt的纯文本数据文件:

hello world
this is the second line 

如果我node read-stream.js target.txttarget.txt的内容会在我的控制台上正常打印,一切都很顺利。

但是如果我用process.stdout.write(chunk);切换console.log(chunk);,那么我得到的结果就是:

<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a 74 68 69 73 20 69 73 20 74 68 65 20 73 65 63 6f 6e 64 20 6c 69 6e 65 0a>

我最近发现,通过执行console.log(chunk.toString());,我的文件内容会再次正常打印。

根据此questionconsole.log应该使用process.stdout.write并添加\n个字符。但是这里编码/解码究竟发生了什么?

提前致谢。

2 个答案:

答案 0 :(得分:5)

process.stdout是一个流,其write()函数只接受字符串和缓冲区。 chunk是一个Buffer对象,process.stdout.write直接在控制台中写入数据字节,因此它们显示为字符串。 console.log在输出之前构建Buffer对象的字符串表示形式,因此开头的<Buffer表示对象的类型,以下是此缓冲区的字节。

在旁注上,process.stdout是一个流,你可以直接管道而不是读取每个块:

stream.pipe(process.stdout);

答案 1 :(得分:2)

我相信我发现了正在发生的事情:

NodeJS中console.log的实现是这样的:

Console.prototype.log = function() {
    this._stdout.write(util.format.apply(this, arguments) + '\n');
};

然而,NodeJS中的util.format lib/util.js inspect在任何输入对象上使用util.format方法,而返回对象的字符串表示形式,对调试很有用。

因此,这里发生的是由于console.log&#34;对象转换&#34;,无论何时我们将对象传递给process.stdout.write,该特定对象首先变为字符串表示形式,然后作为字符串传递给process.stdout.write ,最后写入终端。

因此,当我们直接将util.format与缓冲区对象一起使用时,process.stdout.write被完全跳过,并且每个字节都直接写入终端,因为openpyxl旨在直接处理它们。