2012-09-17 75 views
17

我有大的文本文件,範圍介於30MB10GB之間。如何使用Node.js來計算文件中的行數?Node.js:計算文件中的行數

我有以下限制:

  • 整個文件不需要被寫入到內存
  • 執行
+5

'wc -l file' ... – zerkms

+0

「使用NodeJS」 - 背後的任何真正的技術原因? – zerkms

+2

我相信'wc'會比任何「native」nodejs解決方案更快 – zerkms

回答

22

解決方案沒有我們荷蘭國際集團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.6S + 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 
+3

你的基準測試並不是很有說服力,因爲你在一個文件上運行它,而這個文件不是*結構化成行,因此它不代表OP要處理的文件。 'if(chunk [i] == 10)count ++;'行在分析文本文件的過程中會比在分析二進制視頻文件的過程中更頻繁地執行。 – ebohlman

+0

我沒有100MB的文本文件:)我不想到竟然在類似100MB的文本文件的情況下,但10倍數量的換行有什麼區別 - 這是相同的線性搜索迭代中的每個緩衝塊 –

+0

我複製的每個字節輸入腳本本身並將其連接到單個文本文件,即1468750000個字符,62500000行。 WC時間:0m1.375s,node.js時間:0m6.254s。相同的4.5倍差異(這可能會更好,但仍然足夠JS和C程序) –

17

你可以這樣做的任務一個孩子過程中不需要意見建議使用wc

var exec = require('child_process').exec; 

exec('wc /path/to/file', function (error, results) { 
    console.log(results); 
}); 
+10

'wc'是一個bash特定命令,可能在例如 – Renaud

+1

'WC -l' Windows環境中只能算行數 –

+1

'WC -l路徑/到/ file'將無法正常工作給行數和文件名。行用'廁所-l <路徑/到/ file' – Sarita

1

因爲iojs 1.5.0有Buffer#indexOf()方法,用它來比較Andrey Sidorov的回答:

[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]:~$ 
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); 
+0

爲10GB的文件,這不是很高性能,至少可以說。 –

1

您還可以使用的indexOf():

var index = -1; 
var count = 0; 
while ((index = chunk.indexOf(10, index + 1)) > -1) count++; 
3
var fs=require('fs'); 
filename=process.argv[2]; 
var data=fs.readFileSync(filename); 
var res=data.toString().split('\n').length; 
console.log(res-1);` 
+1

雖然這個代碼片斷可以解決的問題,[包括說明](https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高您的文章質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。也請儘量不要用解釋性註釋來擠佔代碼,這會降低代碼和解釋的可讀性! –

+0

該解決方案需要將文件加載到內存中。我會建議反對它。使用'wc'的答案並不是因爲'wc'被優化來傳輸文件。 –

+0

答案還沒有添加任何東西比較有價值的[艾倫Viars(https://stackoverflow.com/a/32286822/238978)誰在一年前發佈了同樣的事情。 –

1

有一個叫count-lines-in-file的NPM模塊。我一直在使用它爲小(< 1000行)文件,它迄今爲止工作很好。

3

我們可以使用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循環的兩倍。

+1

這是與其他人展示的最佳解決方案! – loretoparisi