2015-12-11 19 views
7

我需要解析的文件裏逐行在以下格式的Node.js:從文件中讀取同步線的Node.js

13 
13 
0 5 
4 3 
0 1 
9 12 
6 4 
5 4 
0 2 
11 12 
9 10 
0 6 
7 8 
9 11 
5 3 

它代表了一個曲線圖。前兩行是邊和頂點的數量,後面是邊。

我可以像完成任務:

var fs = require('fs'); 
var readline = require('readline'); 
var read_stream = fs.createReadStream(filename); 
var rl = readline.createInterface({ 
    input: read_stream 
}); 
var c = 0; 
var vertexes_number; 
var edges_number; 
var edges = []; 
rl.on('line', function(line){ 
    if (c==0) { 
     vertexes_number = parseInt(line); 
    } else if (c==1) { 
     edges_number = parseInt(line); 
    } else { 
     edges.push(line.split(' ')); 
    } 
    c++; 
}) 
.on('end', function(){ 
    rl.close(); 
}) 

我明白這樣的事情可能不是什麼Node.js的被認爲對的,但在line回調級聯if並沒有真正看起來優雅/可讀的。

有沒有一種方法可以像其他編程語言一樣同步讀取流中的行?

如果沒有內置解決方案,我打算使用插件。

[編輯]

對不起,我應該有更明確的是我想,以避免加載在內存中預先

+0

https://nodejs.org/api/fs.html#fs_fs_readfilesync_file_options –

+0

是用'fs.readFileSync'加載它,然後換行分割後同步與您的代碼解析它,即'線= fs.readFileSync('graph.txt')。split(/ [\ n \ r] /);' –

回答

6

上github.com該項目不正是我需要的:

https://github.com/nacholibre/node-readlines

var readlines = require('n-readlines'); 
var liner = new readlines(filename); 

var vertexes_number = parseInt(liner.next().toString('ascii')); 
var edges_number = parseInt(liner.next().toString('ascii')); 
var edges = []; 
var next; 
while (next = liner.next()) { 
    edges.push(next.toString('ascii').split(' ')); 
} 
+0

有沒有一種好的方法來與標準輸入做到這一點?我正在使用代碼提交網站,並且無法將/ dev/stdin作爲文件讀取。 –

+0

如果您在此處發佈了更多詳細信息而不是評論,那麼您將有更好的機會獲得答案。 –

+0

已完成http://stackoverflow.com/questions/43638105/how-to-get-synchronous-readline-or-simulate-it-using-async-in-nodejs –

11

這種簡單的任務,我通常的部分代碼整個文件:

var lines = require('fs').readFileSync(filename, 'utf-8') 
    .split('\n') 
    .filter(Boolean); 

lines是一個沒有空字符串的數組。

+5

謝謝。不過,我仍然對不會在內存中加載整個文件的精益解決方案感興趣。 –

+2

這種方式不能處理大文件,比如10000000行日誌文件,因爲你可以用緩衝區加載大文件到內存,但是nodejs toString方法不能處理太大的緩衝區對象。 – zhuyingda

0

個人而言,我喜歡使用event-stream來處理流。這裏沒有必要,但是我使用它作爲代碼示例。這很簡單,我解析成int,並把裏面的一切edges,那麼當文件讀取完成後,我採取的第一個元素至極爲vertexes_number,新的第一元素是edges_number

var fs = require('fs'); 
var es = require('event-stream'); 

var filename = 'parse-file.txt'; 

var vertexes_number, edges_number; 
var edges = []; 

fs.createReadStream(filename) 
    .pipe(es.split()) // split by lines 
    .pipe(es.map(function (line, next) { 
     // split and convert all to numbers 
     edges.push(line.split(' ').map((n) => +n)); 

     next(null, line); 
    })).pipe(es.wait(function (err, body) { 
     // the first element is an array containing vertexes_number 
     vertexes_number = edges.shift().pop(); 

     // the following element is an array containing edges_number 
     edges_number = edges.shift().pop(); 

     console.log('done'); 
     console.log('vertexes_number: ' + vertexes_number); 
     console.log('edges_number: ' + edges_number); 
     console.log('edges: ' + JSON.stringify(edges, null, 3)); 
    })); 
+0

如果不需要將整個文件加載到內存中,這是迄今爲止最好的方法。 –

+0

是的,這是非常好的方法,但仍然是異步,問題陳述同步模式,雖然沒有用於這種情況。 –

1

爲何不看看他們都爲數組,然後用拼接取出前兩個元素。我假設你的例子很簡單,否則你只需要將整個文件讀入內存並分割即可。如果您的實際情況下存儲多個圖形,你想要做的事時,每一個被加載,例如,你可以把一個測試你的在線活動

var fs = require('fs'); 
var readline = require('readline'); 
var read_stream = fs.createReadStream(filename); 
var rl = readline.createInterface({ 
    input: read_stream 
}); 

var buffer = []; 

rl.on('line', function(line){ 
    buffer.push(line.split(' ')); 
    //Not sure what your actual requirement is but if you want to do 
    //something like display a graph once one has loaded 
    //obviously need to be able to determine when one has completed loading 
    if (buffer.length == GRAPHLENGTH) { //or some other test 
     displayGraph(buffer); 
     buffer = []; 
    }  
}) 
.on('end', function(){ 
    //or do it here if there is only one graph 
    //displayGraph(buffer); 
    rl.close(); 
}) 

function displayGraph(buffer){ 
    var vertexes_number = parseInt(buffer.splice(0,1)); 
    var edges_number = parseInt(buffer.splice(0,1)); 
    var edges = buffer; 

    //doYourThing(vertexes_number, edges_number, edges); 
} 
+1

應該指出的是,在文件系統的情況下,沒有'end'事件,而是'close'在文件結尾處被命中。 –