从Node.js中的文件同步读取行

我需要使用Node.js以下列格式逐行parsing文件:

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的想法,但iflinecallback中级联,看起来并不是那么优雅/可读。

有没有一种方法像在其他编程语言中一样同步读取stream中的行?

如果没有内置解决scheme,我打算使用插件。

[编辑]

对不起,我应该更清楚一点, 我想避免事先加载整个文件在内存中

       

网上收集的解决方案 "从Node.js中的文件同步读取行"

我通常的代码部分为这样简单的任务:

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

lines是一个没有空的string数组。

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(' ')); } 

为什么不把它们全部读入一个数组,然后用拼接取出前两个元素。 我假设你的例子是非常简单的,否则你只是将整个文件读入内存并分割它。 如果您的实际案例存储多个图表,并且您希望在每个图表加载时执行某些操作,则可以在行项目事件中进行testing

 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); } 

我个人喜欢用event-stream处理stream。 这里没有必要,但是我用它作为代码示例。 这很简单,我parsing为int并将所有内容放在edges ,然后当文件读取完成后,我把第一个元素edges_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)); }));