Node.js: подсчитать количество строк в файле
У меня есть большие текстовые файлы, которые находятся между 30MB
и 10GB
. Как подсчитать количество строк в файле с помощью Node.js
?
У меня есть следующие ограничения:
- Весь файл не нужно записывать в память
- Для выполнения задачи не требуется дочерний процесс
Ответы
Ответ 1
без использования 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);
});
он медленнее, но не так много, как вы могли ожидать - 0,6 с для файла 140M +, включая node.js загрузку и время запуска
>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
Ответ 2
Вы можете сделать это, поскольку комментарии предполагают использование wc
var exec = require('child_process').exec;
exec('wc /path/to/file', function (error, results) {
console.log(results);
});
Ответ 3
Вот еще один способ без так много вложенности.
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);
Ответ 4
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
Мы можем использовать indexOf, чтобы виртуальная машина находила символы новой строки:
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 время выполнения для нас, которое выполняется на более низком уровне и должно быть быстрее.
В моей системе это примерно в два раза быстрее, чем запуск цикла for
по длине буфера в большом файле (111 МБ).
Ответ 6
так как iojs 1.5.0 существует метод Buffer#indexOf()
, используя его для сравнения с ответом Андрея Сидорова:
[email protected]:~$ wc logs
7342500 27548750 427155000 logs
[email protected]:~$ time wc -l logs
7342500 logs
real 0m0.180s
user 0m0.088s
sys 0m0.084s
[email protected]:~$ nvm use node
Now using node v0.12.1
[email protected]:~$ time node countlines.js logs
7342500
real 0m2.559s
user 0m2.200s
sys 0m0.340s
[email protected]:~$ nvm use iojs
Now using node iojs-v1.6.2
[email protected]:~$ time iojs countlines2.js logs
7342500
real 0m1.363s
user 0m0.920s
sys 0m0.424s
[email protected]:~$ 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);
});
[email protected]:~$ 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);
});
[email protected]:~$
Ответ 7
Вы также можете использовать indexOf():
var index = -1;
var count = 0;
while ((index = chunk.indexOf(10, index + 1)) > -1) count++;
Ответ 8
Существует модуль npm, называемый count-lines-in-file. Я использовал его для небольших (< 1000 строк) файлов, и он отлично работал до сих пор.