Node.js 将流式缓冲区转换为utf8字符串
我想使用node.js发出HTTP请求,从Web服务器加载一些文本。因为响应可能包含很多文本(一些兆字节),所以我想分别处理每个文本块。我可以使用以下代码实现这一点:Node.js 将流式缓冲区转换为utf8字符串,node.js,Node.js,我想使用node.js发出HTTP请求,从Web服务器加载一些文本。因为响应可能包含很多文本(一些兆字节),所以我想分别处理每个文本块。我可以使用以下代码实现这一点: var req = http.request(reqOptions, function(res) { ... res.setEncoding('utf8'); res.on('data', function(textChunk) { // process utf8 text chunk
var req = http.request(reqOptions, function(res) {
...
res.setEncoding('utf8');
res.on('data', function(textChunk) {
// process utf8 text chunk
});
});
这似乎没有问题。但是我想支持HTTP压缩,所以我使用zlib:
var zip = zlib.createUnzip();
// NO res.setEncoding('utf8') here since we need the raw bytes for zlib
res.on('data', function(chunk) {
// do something like checking the number of bytes downloaded
zip.write(chunk); // give the raw bytes to zlib, s.b.
});
zip.on('data', function(chunk) {
// convert chunk to utf8 text:
var textChunk = chunk.toString('utf8');
// process utf8 text chunk
});
对于像'\u00c4'
这样由两个字节组成的多字节字符,这可能是一个问题:0xC3
和0x84
。如果第一个字节被第一个块(Buffer
)覆盖,第二个字节被第二个块覆盖,则chunk.toString('utf8')
将在文本块的结尾/开头产生不正确的字符。我怎样才能避免这种情况
提示:我仍然需要缓冲区(更具体地说是缓冲区中的字节数)来限制下载的字节数。因此,使用res.setEncoding('utf8')
类似于上面第一个示例代码中的非压缩数据不适合我的需要。Single Buffer
如果您有一个缓冲区
,您可以使用它的方法,使用特定编码将所有或部分二进制内容转换为字符串。如果不提供参数,则默认为utf8
,但我在本例中明确设置了编码
var req = http.request(reqOptions, function(res) {
...
res.on('data', function(chunk) {
var textChunk = chunk.toString('utf8');
// process utf8 text chunk
});
});
流式缓冲器
如果您有如上问题所述的流式缓冲区,其中多字节UTF8
-字符的第一个字节可能包含在第一个缓冲区
(块)中,第二个字节可能包含在第二个缓冲区
中,那么您应该使用:
这样,不完整字符的字节由StringDecoder
缓冲,直到所有需要的字节都写入解码器。var fs=require(“fs”);
var fs = require("fs");
function readFileLineByLine(filename, processline) {
var stream = fs.createReadStream(filename);
var s = "";
stream.on("data", function(data) {
s += data.toString('utf8');
var lines = s.split("\n");
for (var i = 0; i < lines.length - 1; i++)
processline(lines[i]);
s = lines[lines.length - 1];
});
stream.on("end",function() {
var lines = s.split("\n");
for (var i = 0; i < lines.length; i++)
processline(lines[i]);
});
}
var linenumber = 0;
readFileLineByLine(filename, function(line) {
console.log(++linenumber + " -- " + line);
});
函数readFileLineByLine(文件名,进程行){
var stream=fs.createReadStream(文件名);
var s=“”;
stream.on(“数据”,函数(数据){
s+=data.toString('utf8');
变量行=s.split(“\n”);
对于(变量i=0;i
您还可以使用tochunk.toString('utf8');请在您的答案中添加上述建议作为更新,以利于其他人。非常感谢@joshperry:sry,但正如我的问题文本所解释的:chunk.toString('utf8')
并不总是有效,因为utf8中有多字节字符。我不明白你为什么要更改我的答案,它通过使用StringDecoder
明确地解决了这个问题。我错过什么了吗?node
更改了什么吗?我更改了主题标题并编辑了答案。它现在展示了两种解决方案:使用toString
转换流式缓冲区和单个缓冲区。感谢您展示了如何正确处理多字节字符被分割成块的情况。互联网上的许多其他资源完全忽略了这一点,这导致了错误代码的产生,而这些错误代码在投入生产之前通常不会失败。
var fs = require("fs");
function readFileLineByLine(filename, processline) {
var stream = fs.createReadStream(filename);
var s = "";
stream.on("data", function(data) {
s += data.toString('utf8');
var lines = s.split("\n");
for (var i = 0; i < lines.length - 1; i++)
processline(lines[i]);
s = lines[lines.length - 1];
});
stream.on("end",function() {
var lines = s.split("\n");
for (var i = 0; i < lines.length; i++)
processline(lines[i]);
});
}
var linenumber = 0;
readFileLineByLine(filename, function(line) {
console.log(++linenumber + " -- " + line);
});