我有大文本文件,范围介于30MB
和10GB
之间。如何使用Node.js
计算文件中的行数?
我有这些限制:
答案 0 :(得分:28)
解决方案,不使用wc:
var i;
var count = 0;
require('fs').createReadStream(process.argv[2])
.on('data', function(chunk) {
for (i=0; i < chunk.length; ++i)
if (chunk[i] == 10) count++;
})
.on('end', function() {
console.log(count);
});
速度较慢,但没有那么多你可能期望 - 140M +文件的0.6s,包括node.js loading&amp;启动时间
>time node countlines.js video.mp4
619643
real 0m0.614s
user 0m0.489s
sys 0m0.132s
>time wc -l video.mp4
619643 video.mp4
real 0m0.133s
user 0m0.108s
sys 0m0.024s
>wc -c video.mp4
144681406 video.mp4
答案 1 :(得分:24)
您可以根据评论建议使用wc
var exec = require('child_process').exec;
exec('wc /path/to/file', function (error, results) {
console.log(results);
});
答案 2 :(得分:13)
我们可以使用indexOf让VM找到新行:
function countFileLines(filePath){
return new Promise((resolve, reject) => {
let lineCount = 0;
fs.createReadStream(filePath)
.on("data", (buffer) => {
let idx = -1;
lineCount--; // Because the loop will run once for idx=-1
do {
idx = buffer.indexOf(10, idx+1);
lineCount++;
} while (idx !== -1);
}).on("end", () => {
resolve(lineCount);
}).on("error", reject);
});
};
此解决方案的作用是使用.indexOf
找到第一个换行符的位置。它递增lineCount
,然后找到下一个位置。 .indexOf
的第二个参数告诉我们从哪里开始寻找换行符。这样我们就跳过缓冲区的大块。对于每个换行,while循环将运行一次,加上一个。
我们让Node运行时搜索我们,这是在较低级别实现的,应该更快。
在我的系统上,这大约是在大文件(111 MB)上缓冲区长度上运行for
循环的速度的两倍。
答案 3 :(得分:4)
因为iojs 1.5.0有Buffer#indexOf()
方法,用它来与Andrey Sidorov的答案进行比较:
ubuntu@server:~$ wc logs
7342500 27548750 427155000 logs
ubuntu@server:~$ time wc -l logs
7342500 logs
real 0m0.180s
user 0m0.088s
sys 0m0.084s
ubuntu@server:~$ nvm use node
Now using node v0.12.1
ubuntu@server:~$ time node countlines.js logs
7342500
real 0m2.559s
user 0m2.200s
sys 0m0.340s
ubuntu@server:~$ nvm use iojs
Now using node iojs-v1.6.2
ubuntu@server:~$ time iojs countlines2.js logs
7342500
real 0m1.363s
user 0m0.920s
sys 0m0.424s
ubuntu@server:~$ cat countlines.js
var i;
var count = 0;
require('fs').createReadStream(process.argv[2])
.on('data', function(chunk) {
for (i=0; i < chunk.length; ++i)
if (chunk[i] == 10) count++;
})
.on('end', function() {
console.log(count);
});
ubuntu@server:~$ cat countlines2.js
var i;
var count = 0;
require('fs').createReadStream(process.argv[2])
.on('data', function(chunk) {
var index = -1;
while((index = chunk.indexOf(10, index + 1)) > -1) count++
})
.on('end', function() {
console.log(count);
});
ubuntu@server:~$
答案 4 :(得分:2)
var fs=require('fs');
filename=process.argv[2];
var data=fs.readFileSync(filename);
var res=data.toString().split('\n').length;
console.log(res-1);`
答案 5 :(得分:1)
这是没有那么多嵌套的另一种方式。
var fs = require('fs');
filePath = process.argv[2];
fileBuffer = fs.readFileSync(filePath);
to_string = fileBuffer.toString();
split_lines = to_string.split("\n");
console.log(split_lines.length-1);
答案 6 :(得分:1)
您也可以使用indexOf():
var index = -1;
var count = 0;
while ((index = chunk.indexOf(10, index + 1)) > -1) count++;
答案 7 :(得分:1)
有一个名为count-lines-in-file的npm模块。我已经将它用于小型(<1000行)文件,到目前为止它的工作效果很好。
答案 8 :(得分:1)
如果您使用的是Node 8及更高版本,则可以使用这种异步/等待模式
_Bool
答案 9 :(得分:0)
我发现的最佳解决方案是使用promises,async和await。这也是一个如何等待履行承诺的例子:
#!/usr/bin/env node
const fs = require('fs');
const readline = require('readline');
function main() {
function doRead() {
return new Promise(resolve => {
var inf = readline.createInterface({
input: fs.createReadStream('async.js'),
crlfDelay: Infinity
});
var count = 0;
inf.on('line', (line) => {
console.log(count + ' ' + line);
count += 1;
});
inf.on('close', () => resolve(count));
});
}
async function showRead() {
var x = await doRead();
console.log('line count: ' + x);
}
showRead();
}
main();