2015-12-11 12 views
7

tôi cần phải phân tích một dòng tập tin bằng cách dòng trong các định dạng sau đây với Node.js:đọc dòng đồng bộ từ tập tin trong 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 

Nó đại diện cho một đồ thị. Hai dòng đầu tiên là số cạnh và đỉnh, tiếp theo là các cạnh.

tôi có thể hoàn thành nhiệm vụ với một cái gì đó như:

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

Tôi hiểu loại này điều có thể không phải những gì Node.js được suy nghĩ, nhưng cascaded if trong line gọi lại không thực sự trông thanh lịch/có thể đọc được với tôi.

Có cách nào để đọc các dòng đồng bộ từ luồng như trong mọi ngôn ngữ lập trình khác không?

Tôi đang mở để sử dụng plugin nếu không có giải pháp tích hợp.

[EDIT]

Xin lỗi, tôi đã làm nên rõ ràng hơn rằng Tôi muốn tránh tải toàn bộ tập tin trong bộ nhớ trước

+0

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

+0

có tải nó với 'fs.readFileSync' và sau đó phân tích nó với mã của bạn đồng bộ sau khi chia tách bằng dòng mới tức là 'dòng = fs.readFileSync ('graph.txt'). split (/ [\ n \ r] /); ' –

Trả lời

6

Dự án này trên github.com thực hiện chính xác những gì tôi cần:

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

là có một cách tốt để làm điều này với stdin? Tôi đang sử dụng trang web gửi mã và không thể đọc/dev/stdin dưới dạng tệp. –

+0

Bạn sẽ có cơ hội nhận được câu trả lời tốt hơn nếu bạn đăng câu hỏi mới với nhiều chi tiết hơn là nhận xét ở đây. –

+0

Đã hoàn tất http://stackoverflow.com/questions/43638105/how-to-get-synchronous-readline-or-simulate-it-using-async-in-nodejs –

11

phần đang thông thường của tôi cho các nhiệm vụ đơn giản như vậy:

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

lines là một chuỗi các chuỗi không có chuỗi trống.

+5

Cảm ơn. Tuy nhiên tôi vẫn quan tâm đến các giải pháp nạc không tải toàn bộ tập tin trong bộ nhớ. –

+2

Bằng cách này không thể xử lý tệp lớn, chẳng hạn như 10000000 dòng tệp nhật ký, vì bạn có thể tải tệp lớn vào bộ nhớ bằng bộ đệm, nhưng phương thức toString của nodejs không thể xử lý đối tượng đệm quá lớn. – zhuyingda

0

Cá nhân, tôi thích sử dụng event-stream để xử lý luồng. Nó không cần thiết ở đây nhưng tôi đã sử dụng nó cho mẫu mã. Rất đơn giản, tôi phân tích để int và đặt tất cả mọi thứ bên trong edges, sau đó khi đọc tập tin được thực hiện, tôi lấy Mà yếu tố đầu tiên là vertexes_number, yếu tố đầu tiên mới là 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

Đây là phương pháp tốt nhất cho đến nay nếu bạn không cần tải toàn bộ tệp vào bộ nhớ. –

+0

Vâng, nó rất tốt phương pháp này, nhưng vẫn không đồng bộ, các câu hỏi nói chế độ đồng bộ, không hữu ích cho trường hợp này mặc dù. –

1

Tại sao không đọc tất cả chúng vào một mảng và sau đó đưa ra hai yếu tố đầu tiên với mối nối. Tôi cho rằng ví dụ của bạn được đơn giản hóa nhiều hoặc nếu không bạn sẽ chỉ đọc toàn bộ tệp vào bộ nhớ và chia nhỏ nó. Nếu trường hợp thực tế của bạn lưu trữ nhiều đồ thị và bạn muốn làm điều gì đó khi mỗi người được nạp ví dụ, bạn có thể đặt một kiểm tra trong trường hợp dòng của bạn

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

Cần lưu ý rằng trong trường hợp hệ thống tập tin không có sự kiện 'kết thúc' nhưng' close' được phát ra khi kết thúc tập tin. –

Các vấn đề liên quan