[英]Node.js: Count the number of lines in a file
我有很大的文本文件,范圍在30MB
到10GB
之間。 如何使用Node.js
文件中的行數?
我有這些限制:
不使用 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.6 秒,包括 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
您可以按照評論建議使用wc
執行此操作
var exec = require('child_process').exec;
exec('wc /path/to/file', function (error, results) {
console.log(results);
});
我們可以使用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
循環的兩倍。
由於 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:~$
如果您使用 Node 8 及更高版本,則可以使用此 async/await 模式
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function fileLineCount({ fileLocation }) {
const { stdout } = await exec(`cat ${fileLocation} | wc -l`);
return parseInt(stdout);
};
// Usage
async someFunction() {
const lineCount = await fileLineCount({ fileLocation: 'some/file.json' });
}
這是另一種沒有太多嵌套的方法。
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);
var fs=require('fs');
filename=process.argv[2];
var data=fs.readFileSync(filename);
var res=data.toString().split('\n').length;
console.log(res-1);`
我發現的最佳解決方案是使用 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();
您還可以使用 indexOf():
var index = -1;
var count = 0;
while ((index = chunk.indexOf(10, index + 1)) > -1) count++;
有一個名為count-lines-in-file的 npm 模塊。 我一直將它用於較小的(<1000 行)文件,到目前為止效果很好。
使用readline
的簡單解決方案:
import readline from 'node:readline';
export default async function countLines(input) {
let lineCount = 0;
for await (const _ of readline.createInterface({input, crlfDelay: Infinity})) {
lineCount++;
}
return lineCount;
}
import fs from 'node:fs';
console.log(await countLines(fs.createReadStream('file.txt')));
//=> <number>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.