Node.js 逐行讀取

2022-02-26 10:29 更新

本節(jié)介紹Node.js readline(逐行讀?。┠K,它用于提供一個(gè)接口。

穩(wěn)定性: 2 - 不穩(wěn)定

通過 require('readline'),你可以使用這個(gè)模塊。逐行讀取(Readline)可以逐行讀取流(比如process.stdin)。

訪問該模塊的方法如下:

const readline = require('readline');

一旦你開啟了這個(gè)模塊,node程序?qū)⒉粫K止,直到你關(guān)閉接口。以下的代碼展示了如何優(yōu)雅的退出程序:

var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question("What do you think of node.js? ", function(answer) {
  // TODO: Log the answer in a database
  console.log("Thank you for your valuable feedback:", answer);

  rl.close();
});

readline.createInterface(options)

創(chuàng)建一個(gè)逐行讀取(Readline)Interface實(shí)例。參數(shù)"options"對象有以下值:

  • input- 監(jiān)聽的可讀流 (必填)。

  • output- 逐行讀取(Readline)數(shù)據(jù)要寫入的可寫流(可選)。

  • completer- 用于Tab自動補(bǔ)全的可選函數(shù)。參見下面的例子。

  • terminal- 如果希望和TTY一樣,對待inputoutput流,設(shè)置為true。并且由ANSI/VT100轉(zhuǎn)碼。默認(rèn)情況下,檢查isTTY是否在output流上實(shí)例化。

completer給出當(dāng)前行的入口,應(yīng)該返回包含2條記錄的數(shù)組。

  1. 一個(gè)匹配當(dāng)前輸入補(bǔ)全的字符串?dāng)?shù)組

  2. 用來匹配的子字符串

最終像這樣:[[substr1, substr2, ...], originalsubstring].

例子:

function completer(line) {
  var completions = '.help .error .exit .quit .q'.split(' ')
  var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })
  // show all completions if none found
  return [hits.length ? hits : completions, line]
}

同時(shí),completer可以異步運(yùn)行,此時(shí)接收到2個(gè)參數(shù):

function completer(linePartial, callback) {
  callback(null, [['123'], linePartial]);
}

為了接受用戶輸入,createInterface通常和process.stdin ,process.stdout一起使用:

var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

如果你有逐行讀?。≧eadline)實(shí)例, 通常會監(jiān)聽"line"事件.

如果這個(gè)實(shí)例參數(shù)terminal = true,而且定義了output.columns屬性,那么output流將會最佳兼容性,并且,當(dāng)columns變化時(shí)(當(dāng)它是TTY時(shí),process.stdout會自動這么做),會在output流上觸發(fā)"resize"事件。

Class: Interface

代表一個(gè)包含輸入/輸出流的逐行讀?。≧eadline)接口的類。

rl.setPrompt(prompt)

設(shè)置提示符,比如當(dāng)你再命令行里運(yùn)行node時(shí),可以看到node的提示符>

rl.prompt([preserveCursor])

為用戶輸入準(zhǔn)備好逐行讀?。≧eadline),將當(dāng)前setPrompt選項(xiàng)方法哦新的行中,讓用戶有新的地方輸入。設(shè)置preserveCursortrue,防止當(dāng)前的游標(biāo)重置為0。

如果暫停,使用createInterface也可以重置input輸入流。

調(diào)用createInterface時(shí),如果output設(shè)置為nullundefined,不會重新寫提示符。

rl.question(query, callback)

預(yù)先提示query,用戶應(yīng)答后觸發(fā)callback。給用戶顯示query后,用戶應(yīng)答被輸入后,調(diào)用callback。

如果暫停,使用createInterface也可以重置input輸入流。

調(diào)用createInterface時(shí),如果output設(shè)置為nullundefined,不會重新寫提示符。

例子:

interface.question('What is your favorite food?', function(answer) {
  console.log('Oh, so your favorite food is ' + answer);
});

rl.pause()

暫停逐行讀?。≧eadline)的input輸入流, 如果需要可以重新啟動。

注意,這不會立即暫停流。調(diào)用pause后還會有很多事件觸發(fā),包含line。

rl.resume()

恢復(fù) 逐行讀?。≧eadline)input輸入流.

rl.close()

關(guān)閉Interface實(shí)例, 放棄控制輸入輸出流。會觸發(fā)"close"事件。

rl.write(data[, key])

調(diào)用createInterface后,將數(shù)據(jù)data寫到output輸出流,除非outputnull,或未定義undefined。key是一個(gè)代表鍵序列的對象;當(dāng)終端是一個(gè) TTY 時(shí)可用。

暫停input輸入流后,這個(gè)方法可以恢復(fù)。

例子:

rl.write('Delete me!');
// Simulate ctrl+u to delete the line written previously
rl.write(null, {ctrl: true, name: 'u'});

Events

事件: 'line'

function (line) {}

input輸入流收到\n后觸發(fā),通常因?yàn)橛脩羟没剀嚮蚍祷劓I。這是監(jiān)聽用戶輸入的好辦法。

監(jiān)聽line的例子:

rl.on('line', function (cmd) {
  console.log('You just typed: '+cmd);
});

事件: 'pause'

function () {}

暫停input輸入流后,會觸發(fā)這個(gè)方法。

當(dāng)輸入流未被暫停,但收到SIGCONT也會觸發(fā)。 (詳見SIGTSTPSIGCONT事件)

監(jiān)聽pause的例子:

rl.on('pause', function() {
  console.log('Readline paused.');
});

事件: 'resume'

function () {}

恢復(fù)input輸入流后,會觸發(fā)這個(gè)方法。

監(jiān)聽resume的例子:

rl.on('resume', function() {
  console.log('Readline resumed.');
});

事件: 'close'

function () {}

調(diào)用close()方法時(shí)會觸發(fā)。

當(dāng)input輸入流收到"end"事件時(shí)會觸發(fā)。一旦觸發(fā),可以認(rèn)為Interface實(shí)例結(jié)束。例如當(dāng)input輸入流收到^D,被當(dāng)做EOT

如果沒有SIGINT事件監(jiān)聽器,當(dāng)input 輸入流接收到^C(被當(dāng)做SIGINT),也會觸發(fā)這個(gè)事件。

事件: 'SIGINT'

function () {}

當(dāng)input輸入流收到^C時(shí)會觸發(fā), 被當(dāng)做SIGINT。如果沒有SIGINT 事件監(jiān)聽器,當(dāng)input 輸入流接收到SIGINT(被當(dāng)做SIGINT),會觸發(fā) pause事件。

監(jiān)聽SIGINT的例子:

rl.on('SIGINT', function() {
  rl.question('Are you sure you want to exit?', function(answer) {
    if (answer.match(/^y(es)?$/i)) rl.pause();
  });
});

事件: 'SIGTSTP'

function () {}

Windows 里不可用

當(dāng)input輸入流收到^Z時(shí)會觸發(fā),被當(dāng)做SIGTSTP。如果沒有SIGINT事件監(jiān)聽器,當(dāng)input 輸入流接收到SIGTSTP,程序?qū)袚Q到后臺。

當(dāng)程序通過fg恢復(fù),將會觸發(fā)pauseSIGCONT事件。你可以使用兩者中任一事件來恢復(fù)流。

程切換到后臺前,如果暫停了流,pauseSIGCONT事件不會被觸發(fā)。

監(jiān)聽SIGTSTP的例子:

rl.on('SIGTSTP', function() {
  // This will override SIGTSTP and prevent the program from going to the
  // background.
  console.log('Caught SIGTSTP.');
});

事件: 'SIGCONT'

function () {}

Windows里不可用

一旦input流中含有^Z并被切換到后臺就會觸發(fā)。被當(dāng)做SIGTSTP,然后繼續(xù)執(zhí)行fg(1)。程切換到后臺前,如果流沒被暫停,這個(gè)事件可以被觸發(fā)。

監(jiān)聽SIGCONT的例子:

rl.on('SIGCONT', function() {
  // `prompt` will automatically resume the stream
  rl.prompt();
});

例子: Tiny CLI

以下的例子,展示了如何所有這些方法的命令行接口:

var readline = require('readline'),
    rl = readline.createInterface(process.stdin, process.stdout);

rl.setPrompt('OHAI> ');
rl.prompt();

rl.on('line', function(line) {
  switch(line.trim()) {
    case 'hello':
      console.log('world!');
      break;
    default:
      console.log('Say what? I might have heard `' + line.trim() + '`');
      break;
  }
  rl.prompt();
}).on('close', function() {
  console.log('Have a great day!');
  process.exit(0);
});

readline.cursorTo(stream, x, y)

在TTY流里,移動光標(biāo)到指定位置。

readline.moveCursor(stream, dx, dy)

在TTY流里,移動光標(biāo)到當(dāng)前位置的相對位置。

readline.clearLine(stream, dir)

清空TTY流里指定方向的行。dir是以下值:

  • -1- 從光標(biāo)到左邊
  • 1- 從光標(biāo)到右邊
  • 0- 整行

readline.clearScreenDown(stream)

清空屏幕上從當(dāng)前光標(biāo)位置起的內(nèi)容。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號