2012-11-16 44 views
19

Trong RingoJS có function được gọi là read cho phép bạn đọc toàn bộ luồng cho đến khi kết thúc đạt được. Điều này rất hữu ích khi bạn đang tạo một ứng dụng dòng lệnh. Ví dụ, bạn có thể viết một tacprogram như sau:Cách đọc toàn bộ luồng văn bản trong node.js?

#!/usr/bin/env ringo 

var string = system.stdin.read(); // read the entire input stream 
var lines = string.split("\n"); // split the lines 

lines.reverse();     // reverse the lines 

var reversed = lines.join("\n"); // join the reversed lines 
system.stdout.write(reversed); // write the reversed lines 

này cho phép bạn cháy lên một vỏ và chạy lệnh tac. Sau đó, bạn gõ vào như nhiều dòng như bạn muốn và sau khi bạn đã hoàn tất, bạn có thể nhấn tổ hợp phím Ctrl + D (hoặc Ctrl +Z trên Windows) để báo hiệu end of transmission.

Tôi muốn làm điều tương tự trong node.js nhưng tôi không thể tìm thấy bất kỳ chức năng nào có thể làm như vậy. Tôi nghĩ đến việc sử dụng readSyncfunction từ thư viện fs để mô phỏng như sau, nhưng không có kết quả:

fs.readSync(0, buffer, 0, buffer.length, null); 

Các file descriptor for stdin (đối số đầu tiên) là 0. Vì vậy, nó nên đọc dữ liệu từ bàn phím. Thay vào đó, nó cung cấp cho tôi lỗi sau:

Error: ESPIPE, invalid seek 
    at Object.fs.readSync (fs.js:381:19) 
    at repl:1:4 
    at REPLServer.self.eval (repl.js:109:21) 
    at rli.on.self.bufferedCmd (repl.js:258:20) 
    at REPLServer.self.eval (repl.js:116:5) 
    at Interface.<anonymous> (repl.js:248:12) 
    at Interface.EventEmitter.emit (events.js:96:17) 
    at Interface._onLine (readline.js:200:10) 
    at Interface._line (readline.js:518:8) 
    at Interface._ttyWrite (readline.js:736:14) 

Làm cách nào bạn đồng bộ thu thập tất cả dữ liệu trong luồng văn bản đầu vào và trả về dưới dạng chuỗi trong node.js? Một ví dụ mã sẽ rất hữu ích.

+0

Bạn không thể đọc đồng bộ trong luồng không đồng bộ. Tại sao bạn muốn sao? – tjameson

+0

Tôi đang cố gắng làm điều tương tự. Lý do là tạo ra một tùy chọn tương tác trong chương trình của tôi, hữu ích vì nhiều lý do. Một người đọc không đồng bộ không giúp quá nhiều. – ton

+0

đây là cách https: //www.npmjs.com/package/readline-sync: http://stackoverflow.com/questions/8452957/synchronously-reading-stdin-in-windows/27931290#27931290 – ton

Trả lời

12

Điều quan trọng là sử dụng hai sự kiện Suối:

Event: 'data' 
Event: 'end' 

Đối stream.on('data', ...) bạn nên thu thập dữ liệu dữ liệu của bạn vào hoặc là một bộ đệm (nếu nó là nhị phân) hoặc vào một chuỗi.

Đối với on('end', ...) bạn nên gọi lại bằng bộ đệm đã hoàn thành hoặc nếu bạn có thể đặt nội tuyến và sử dụng trả lại bằng thư viện Promises.

27

Như Node.js là sự kiện và dòng định hướng không có API để chờ cho đến khi kết thúc stdin và kết quả đệm, nhưng nó dễ dàng để làm bằng tay

var content = ''; 
process.stdin.resume(); 
process.stdin.on('data', function(buf) { content += buf.toString(); }); 
process.stdin.on('end', function() { 
    // your code here 
    console.log(content.split('').reverse().join('')); 
}); 

Trong hầu hết các trường hợp, nó là tốt hơn không để đệm dữ liệu và xử lý các đoạn đến khi chúng đến (sử dụng chuỗi các trình phân tích luồng sẵn có như xml hoặc zlib hoặc trình phân tích cú pháp FSM của riêng bạn)

+4

Bạn có thể thực hiện 'process.stdin.setEncoding ('utf-8') ; 'sau khi tiếp tục và' lỗi' trong gọi lại sẽ là chuỗi. – Mitar

+2

Tương tự, nhưng sử dụng 'Buffer.concat()': http://stackoverflow.com/questions/10686617/how-can-i-accumulate-a-raw-stream-in-node-js#23304138 – joeytwiddle

+0

@Mitar: đó là 'buf', không phải' lỗi'. – evandrix

5

Có một mô-đun cho nhiệm vụ cụ thể đó, được gọi là concat-stream.

+0

Mô-đun này cho phép bạn để xen các khối với một chuỗi khác. Có lẽ chỉ hữu ích để gỡ lỗi: https://www.npmjs.org/package/join-stream – joeytwiddle

4

Hãy để tôi minh họa cho câu trả lời của StreetStrider.

Dưới đây là làm thế nào để làm điều đó với concat-stream

var concat = require('concat-stream'); 

yourStream.pipe(concat(function(buf){ 
    // buf is a Node Buffer instance which contains the entire data in stream 
    // if your stream sends textual data, use buf.toString() to get entire stream as string 
    var streamContent = buf.toString(); 
    doSomething(streamContent); 
})); 

// error handling is still on stream 
yourStream.on('error',function(err){ 
    console.error(err); 
}); 

Xin lưu ý rằng process.stdin là một dòng suối.

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