Read lines synchronously from file in Node.js

I need to parse the file line by line in the following format using 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 

It is a graph. The first two lines are the number of edges and vertices followed by edges.

I can complete the task with something like:

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

I understand that such things may not be what Node.js was thinking, but the cascading if in the line callback does not really look elegant / readable.

Is there a way to read synchronous lines from a stream, like in any other programming language?

I am open to using plugins if there is no built-in solution.

[EDIT]

Sorry, I had to clarify that I would like to avoid loading the entire file into memory in advance

+16
javascript
source share
4 answers

This github.com project does exactly what I need:

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(' ')); } 
+9
source share

My usual piece of code for such simple tasks:

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

lines is an array of lines without empty lines.

+24
source share

Why not read them all into an array, and then take out the first two elements with a splice. I assume that your example is greatly simplified, otherwise you would just read the entire file into memory and break it. If your real case stores several graphs and you want to do something, for example, when loading each of them, you can put the test in the row event

 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('close', 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
source share

Personally, I like to use event-stream to work with streams. Not needed here, but I used it for sample code. It's simple, I parse the int and put everything inside the edges , then when the file is being read, I take the first element, which is vertexes_number , the new first element 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
source share

All Articles