[新手]Nodejs中在一个简单的hello遇到的Buffer和data事件的问题
[新手]Nodejs中在一个简单的hello遇到的Buffer和data事件的问题
我用浏览器访问一次 http://127.0.0.1 ,为什么会打印出两次一样的内容?'data’是被触发了两次么? 还有,不太清楚读取的buffer前3个字节是什么,后面才是html的数据,但没了这三个字节浏览器会显示乱码
打印: D:\nodejs\test>node test.js server start < Buffer ef bb bf 3c 68 31 3e 68 68 68 68 20 e6 88 91 3c 2f 68 31 3e > 20 < Buffer ef bb bf 3c 68 31 3e 68 68 68 68 20 e6 88 91 3c 2f 68 31 3e > 20
hello.html内容: < h1>hhhh 我< /h1>
代码: var http = require(‘http’); var fs = require(‘fs’);
http.createServer(function (req, res) { var rStream = fs.createReadStream(’./hello.html’); var datas = []; rStream.on(‘data’, function (data) { console.log(data); console.log(data.length); datas.push(data); }); rStream.on(‘end’, function () { var buf = Buffer.concat(datas); res.writeHead(200, {‘Content-Type’: ‘text/html’}); res.end(buf); }); }).listen(80); console.log(‘server start’);
根据你的描述和提供的代码片段,你遇到了两个主要问题:
data
事件被触发两次:这通常是因为每次data
事件被触发时,读取流会传递一部分数据。如果你没有正确地处理这些部分数据,可能会导致多次输出。- 前三个字节的问题:
ef bb bf
这些字节是 UTF-8 编码中的 BOM(Byte Order Mark),用于标识文件以 UTF-8 编码。
示例代码及解释
让我们修改一下你的代码,确保我们正确处理 data
事件,并且去除 BOM。
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
var rStream = fs.createReadStream('./hello.html');
var datas = [];
rStream.on('data', function (data) {
console.log(data.toString());
console.log(data.length);
datas.push(data);
});
rStream.on('end', function () {
// 拼接所有数据片段
var buf = Buffer.concat(datas);
// 去除BOM
if (buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) {
buf = buf.slice(3);
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(buf);
});
}).listen(80);
console.log('server start');
解释
data
事件处理:每次data
事件被触发时,我们将数据片段推入datas
数组,并打印其长度。- 拼接数据:在
end
事件中,我们将所有数据片段拼接到一个Buffer
中。 - 去除 BOM:检查拼接后的
Buffer
是否包含 BOM 字节(0xEF BB BF
),如果存在,则从第四个字节开始截取数据。 - 发送响应:将处理后的
Buffer
发送到客户端。
这样处理后,你可以避免重复输出和 BOM 导致的乱码问题。希望这能解决你的问题!
在 function(req,res)后添加了一行打印 console.log(‘new req’)发觉是发了两次请求……汗,奇怪了
根据你的描述,你在处理文件流读取时遇到了一些问题,特别是在 data
事件中接收到的 Buffer
对象以及 HTML 文件的编码问题。
问题分析
data
事件被触发两次:这通常是因为数据量较大,分成了多个块进行传输。- 前三个字节:这些字节实际上是 UTF-8 的 BOM(Byte Order Mark),即
ef bb bf
。BOM 用于标记文件的编码格式,对于大多数现代浏览器来说,可以忽略它。 - 浏览器显示乱码:这是由于浏览器无法正确解析没有去除 BOM 的数据。
示例代码
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
var rStream = fs.createReadStream('./hello.html');
rStream.on('data', function (data) {
// console.log(data); // 可以注释掉,避免输出过多数据
console.log(data.length);
});
let datas = [];
rStream.on('data', function (data) {
datas.push(data);
});
rStream.on('end', function () {
// 拼接所有数据块
var buf = Buffer.concat(datas);
// 去除 BOM(可选)
if (buf.slice(0, 3).equals(new Buffer([0xEF, 0xBB, 0xBF]))) {
buf = buf.slice(3);
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(buf);
});
}).listen(80);
console.log('server start');
解释
data
事件:每次接收到数据块时,将其添加到数组datas
中。- 拼接数据:在
end
事件中,使用Buffer.concat
方法将所有数据块合并成一个完整的Buffer
。 - 去除 BOM:检查缓冲区的前三个字节是否为 BOM,并在需要时去除它们。
- 发送响应:将最终的
Buffer
发送给客户端。
这样可以确保即使文件较大,数据也能正确地被读取并发送给浏览器,同时不会出现乱码问题。