为什么Node.js的fs.readFile()返回缓冲区而不是字符串?


377

我正在尝试读取test.txt(位于Javascript源的同一文件夹中)的内容,并使用以下代码显示它:

var fs = require("fs");

fs.readFile("test.txt", function (err, data) {
    if (err) throw err;
    console.log(data);
});

的内容test.txt创建于nano

测试Node.js readFile()

我得到这个:

Nathan-Camposs-MacBook-Pro:node_test Nathan$ node main.js
<Buffer 54 65 73 74 69 6e 67 20 4e 6f 64 65 2e 6a 73 20 72 65 61 64 46 69 6c 65 28 29>
Nathan-Camposs-MacBook-Pro:node_test Nathan$ 

Answers:


561

文档:

如果未指定编码,则返回原始缓冲区。

这可能解释了<Buffer ...>。指定一个有效的编码,例如utf-8作为文件名之后的第二个参数。如,

fs.readFile("test.txt", "utf8", function(err, data) {...});

164

尝试

fs.readFile("test.txt", "utf8", function(err, data) {...});

基本上,您需要指定编码。


66

这在Google上很重要,因此我想添加一些有关原始问题的上下文信息(重点是我的):

为什么 Node.js的fs.readFile()返回缓冲区而不是字符串?

因为文件并不总是文本

即使作为程序员,也知道:Node不知道您要读取的文件中的内容。它可以是文本文件,但也可以是ZIP存档或JPG图像-Node不知道。

因为读取文本文件很棘手

即使Node 知道要读取文本文件,也仍然不知道使用哪种字符编码(即文件中的字节如何映射为人类可读的字符),因为字符编码本身未存储在文件中。

有一些方法可以或多或少地猜测文本文件的字符编码(这是文本编辑器在打开文件时所做的事情),但是您通常不希望您的代码在没有明确说明的情况下依靠猜测。

缓冲救援!

因此,因为它不知道所有这些详细信息,所以节点只是逐个字节地读取文件,而无需假设其内容。

这就是返回的缓冲区的内容:原始数据二进制内容的未修饰容器。作为开发人员,应如何解释此内容。


10
这是实际上回答标题中问题的唯一答案。
frzsombor

4
@frzsombor假设有一个接受的答案,我会承担OP真的感兴趣的是得到的字符串,而不是缓冲器,只是不能短语题吧。不过,其他人可能会想到Google来这里就是真正的“为什么”,因此我回答了。:)
卢洛

44

异步:

fs.readFile('test.txt', 'utf8', callback);

同步:

var content = fs.readFileSync('test.txt', 'utf8');

38

它返回一个Buffer对象。

如果要以字符串形式输入,可以使用以下命令进行转换data.toString()

var fs = require("fs");

fs.readFile("test.txt", function (err, data) {
    if (err) throw err;
    console.log(data.toString());
});

13
有点陈旧,但是应该知道此解决方案会带来额外的开销,因为buffer.toString()无论如何都要假设为utf-8编码。因此,这等同于(尽管比@hvgotcodes的答案要慢)。
布兰登

14

data变量包含一个Buffer对象。使用以下语法将其转换为ASCII编码:

data.toString('ascii', 0, data.length)

异步地:

fs.readFile('test.txt', 'utf8', function (error, data) {
    if (error) throw error;
    console.log(data.toString());
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.