我需要使用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的想法,但if
回调中的级联line
对我来说看起来并不优雅/可读。
有没有办法像其他编程语言一样从流中读取同步行?
如果没有内置解决方案,我可以使用插件。
[编辑]
抱歉,我应该更清楚我想避免事先将整个文件加载到内存中
答案 0 :(得分:30)
这些简单任务的常用代码部分:
var lines = require('fs').readFileSync(filename, 'utf-8')
.split('\n')
.filter(Boolean);
lines
是一个没有空字符串的字符串数组。
答案 1 :(得分:10)
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(' '));
}
答案 2 :(得分:1)
为什么不将它们全部读入数组,然后用splice取出前两个元素。我假设您的示例非常简化,否则您只需将整个文件读入内存并将其拆分。如果您的实际案例存储多个图表,并且您希望在每个图表加载时执行某些操作,则可以在行事件中进行测试
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);
}
答案 3 :(得分: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));
}));