我希望你能帮我解决这个问题,基本上就是在Perl中的:
while (<>) {
process_line($_);
}
我的用例只是一个独立的脚本,不是服务器,因此同步方式很好。这些是我的标准:
- 最小同步代码,可在多个项目中重复使用。
- 没有文件大小或行数的限制。
- 没有行长度限制。
- 能够处理UTF-8中的完整Unicode,包括超出BMP的字符。
- 能够处理*nix和Windows行结尾(对我来说,旧式Mac不需要)。
- 包含行结尾字符。
- 能够处理带有或不带有行结尾字符的最后一行。
- 不使用任何未包含在node.js分发中的外部库。
这是一个让我感受node.js低级脚本类型代码并决定它是否可以替代其他脚本语言(如Perl)的项目。
经过惊人的努力和几次失败的尝试后,这是我想出的代码。它相当快,但比我预期的要复杂得多:
(在GitHub上派生它)
var fs = require('fs'),
StringDecoder = require('string_decoder').StringDecoder,
util = require('util');
function lineByLine(fd) {
var blob = '';
var blobStart = 0;
var blobEnd = 0;
var decoder = new StringDecoder('utf8');
var CHUNK_SIZE = 16384;
var chunk = new Buffer(CHUNK_SIZE);
var eolPos = -1;
var lastChunk = false;
var moreLines = true;
var readMore = true;
while (moreLines) {
readMore = true;
while (readMore) {
eolPos = blob.indexOf('\n', blobStart);
if (eolPos !== -1) {
blobEnd = eolPos;
readMore = false;
} else if (lastChunk) {
blobEnd = blob.length;
readMore = false;
} else {
var bytesRead = fs.readSync(fd, chunk, 0, CHUNK_SIZE, null);
lastChunk = bytesRead !== CHUNK_SIZE;
blob += decoder.write(chunk.slice(0, bytesRead));
}
}
if (blobStart < blob.length) {
processLine(blob.substring(blobStart, blobEnd + 1));
blobStart = blobEnd + 1;
if (blobStart >= CHUNK_SIZE) {
var freeable = blobStart / CHUNK_SIZE;
blob = blob.substring(CHUNK_SIZE);
blobStart -= CHUNK_SIZE;
blobEnd -= CHUNK_SIZE;
}
} else {
moreLines = false;
}
}
}
这可能需要进一步清理,这是试错的结果。
fs.readSync()
会发现处理起来非常困难。你可以将二进制八位字节读入缓冲区,但是在将其转化为 JavaScript 字符串并扫描 EOLs(行结束符)之前,没有简单的方法来处理部分 UTF-8 或 UTF-16 字符。Buffer()
类型没有如本地字符串一样丰富的函数集来操作其实例,但是本地字符串无法包含二进制数据。在我看来,缺少从任意文件句柄读取文本行的内置方式是 node.js 中的一个真正差距。 - hippietrailif (line.length==1 && line[0] == 48) special(line);
,以处理这种情况。 - Thabonode
的 API 文档中略有修改,详情请见 https://github.com/nodejs/node/pull/4609。 - eljefedelrodeodeljefe