Node.js核心模块readline

Node.js中文网的 v6.10.3 文档提供了readline模块,可以从可读流(process.stdin)读取数据,Node.js的v6.10.3 版本是长期支持版本,而readline也是比较稳定的API了,下面详细描述一下readline的官方API;之前写了一个从酷狗音乐爬取音乐歌曲的爬虫脚本,但是每次都要从酷狗官网查找歌手的详细地址,现在可以直接可以使用readline模块从命令行窗口读取我们要查找的歌手名称,然后进行拼接处理。

1. <code>require(‘readline’)</code>模块提供了一个接口,用于从可读流中(process.stdin)中读取数据,每次读取一行,由于readline不是Node.js的全局模块变量,所以需要引入readline模块。
require ('readline);
  • 下面是官方给出的readline基本用法:
const readline=require('readline');
const rl=readline.createInterface({
    input:process.stdin,
    output:process.stdout
});
rl.question('你觉得Node.js中文网怎么样?',(answer)=>{
    //对答案进行处理
    console.log(`多谢你的反馈:${answer}`);
    rl.close();
});
  • 运行上述代码并输入你想输入的评价,就可以直接可以输出具体的结果,详细如下:
readline模块
  • 注意,当调用代码时候,Node.js不会终止,只有realine.createInterface被关闭;因为接口在等待 input 流中要被接收的数据。
2. Interface类:readline.Interface类的实例都是使用readline.createInterface()方法构造的。每个实例都关联着一个input可读流和一个output可写流。output流用于用户输入打印显示,output流数据从input流中读取。
  • ‘close’事件:当以下之一发生时,触发'close'事件:
    • rl.close()方法被调用,且readline.Interface实例已经撤回对input流和output流的控制。
    • input流收到end事件。
    • input流收到表示结束传输的<ctrl+D>。
    • input流收到SIGINT的<ctrl+C>,且readline.interface实例上没有注册SIGINT事件监听器。
    • 监听器函数不接受任何参数,当'close'事件被触发时,readline.Interface实例应当被视为结束。
  • ‘line’事件:每当input流收到行结束符(\n ,\r或者\n\r时触发‘line事件。通常发生在用户按下<enter>或<return>键)
    • 监听器函数被调用时会带上一个包含接收哪一行输入的字符,实例如下包括运行结果。
const readline=require('readline');
const rl=readline.createInterface({
    input:process.stdin,
    output:process.stdout
});
rl.on('line',(input)=>{
    console.log(`接收到: ${input}`);
    rl.close();
});
line事件
  • 'pause'事件:当以下之一事件发生时触发'pause'事件:
    • input 流暂停。
    • input 流不是暂停的,且收到SIGONT事件。
    • 监听函数被调用时不传入任何参数。
    • 例子:
rl.on('pause',()=>{
  console,log('Readline 被暂停。');
});
  • ‘resume’事件:每当input流被恢复时触发'resume'事件。监听器函数被调用时不传入任何参数。
    • 实例如下:
rl.on('resume',()=>{
   console.log('Readline 被恢复。');
});
  • ‘SIGCONT’事件:
    • 当一个Node.js进程使用<ctrl +z>(也就是SIGSTP)移入后台之后再使用fg(1)移回前台时,触发'SIGCONT'事件。
    • 如果input流在SIGSTP请求之前被暂停,则事件不会被触发。
    • 监听器函数被调用时不传任何参数。
    • 例子(注意,Windows系统不支持‘SIGCONF’事件):
rl.on('SIGCONF',()=>{
   //'prompt'会自动恢复流
   rl.prompt();
});
  • ‘SIGINT’事件:每当input流接收到一个<ctrl + C>输入(通常被称为SIGINT)时,触发‘SIGINT’事件,当input流接收到一个SIGINT时,如果没有注册‘SIGINT’事件监听器,则‘pause’事件会被触发。
    • 监听器函数被调用时不传入任何参数,例子如下。
rl.on('SIGCONF',()=>{
  rl.question('确定要退出吗?',(answer)=>{
      if(answer.match(/^y(es)?$/i))
          rl.pause();
  });
});
  • 'SIGSTP'事件:每当input流接收到一个<ctrl+z>输入(通常被称为SIGSTP)时,触发‘SIGSTP’事件。当input流接收到一个SIGSTP时,如果没有注册‘SIGSTP’事件监听器,则Node.js进程会被发送到后台。
    • 当程序使用fg(1)恢复时,‘pause’和‘SIGCONF’事件会被触发。这可被用来恢复input流。
    • 如果input流在进程被发送到后台之前被暂停,则‘pause’和‘SIGCONF’事件不会被触发。
    • 实例如下所示(注意,Windows系统不支持‘SIGSTP’):
rl.on('SIGCONF',()=>{
  //这会重写SOGSTP,且防止程序进入后台
  console.log('捕获SIGSTP');
});
  • rl.close():rl.close()方法会关闭readline.Interface实例,且撤回对input和output流的控制。但调用时,close事件会被触发。

  • rl.pause():rl.pause()方法会暂停input流,且稍后需要时可被恢复。调用rl.pause()不会立刻暂停其他事件(包括‘line’)被readline.Interface实例触发。

  • rl.prompt([preserveCursor]):preserveCursor(boolean)如果为true,则阻止光标落点被设置为0。

    • rl.prompt()方法会在output流中新的一行写入readlin.Interface实例配置后的prompt,用于为用户提供一个可供输入新的位置。
    • 当被调用时,如果input流已经被暂停,则rl.prompt()会回复input流。
    • 如果readline.Interface被创建时ouput被设为null或undefined,则提示不会被写入。
  • rl.question(query,callback):

    • query(String)一个在提示符之前、要写入output的叙述或提问。
    • callback(Function)一个回调函数,它会被调用并带上用户响应query的输入。
    • rl.question()方法通过写入output来展示query,并等待用户提供到input的输入,然后调用callback函数并传入提供的输入作为第一个参数。
    • 当被调用,如果input流已被暂停,则rl.question()会恢复input流。
    • 如果readline.Interface被创建时,output被设为null或undefined,则query不会被写入。
    • 实例如下所示(注意,传入的rl.question()的callback函数不支持遵循一个Error对象会Null作为第一个参数的标准模式。callback被调用时只带上提供的答案作为唯一参数):
rl.question('你最喜欢的食物是什么?',(answer)=>{
  console.log(`你最喜欢的食物是 ${answer}`);
});
  • rl.resume():如果input流已被暂停,则rl.resume()方法会恢复input流。

  • rl.setPrompt(prompt):

    • prompt(String):rl.setPrompt()方法用于设置每当rl.prompt()被调用时要被写入output的提示。
  • rl.write(data[,key]):

    • data(String):

    • key(Object):

      • ctrl (boolean)如果为true则表示<ctrl>键
      • meta (boolean)如果为true则表示<Meat>键
      • shift (boolean)如果为true则表示<shift>键
      • name (String)一个按键的名称
    • rl.write()方法会把data或一个由Key指定的按键序列写到output。只有当output是一个TTY文本终端时,Key参数才被支持。

    • 如果指定了key,则data会被忽略。当被调用时,如果input流已经暂停,则rl.write()会恢复input流。

    • 如果readline.Interface被创建时output被设置为null或undefined,则data和key不会写入。

    • 例子如下(注意,rl.write()方法会写入数据到readline接口的input,仿佛他是用户提供的):

rl.write('删除这个!');
//模拟ctrl+u删除写入的前一行
rl.write(null,{
  ctrl:true,
  name:'u'
});
  • readline.clearLine(stream,dir):
    • stream(Writable):
    • dir(number):
      • -1 光标左边
      • 1-光标右边
      • 0 -整行
    • readline.clearLine()方法会以dir指定的方向清除给定的TTY流当前行。
  • readline.clearScreenDown(Strem):
    • stream(writable)
    • readline.clearScreenDown()方法会从光标的当前位置向下清除给定TTY流。
  • readline.createInterface(options):
    • options:(object)
      • input(Readable)要监听的可读流。该选项是必须的。
      • output(Writable)要写入逐行读取数据的可写流。
      • completer(Function):一个可选的函数,用于Tab自动补全。
      • Terminal(boolean):如果input和output应被当做一个tty,且要写入ANSI、VT100转换的代码,则设置为true;默认实例化时在output流上检查isTTY。
      • historySize(number):保留的历时行数的最大数量,设为0课禁用历史记录。默认为30.该选项只有terminal被用户或内部output设为true时才有意义,否则历史缓存机制不会被初始化。
      • prompt -要使用的提示字符串。默认为'>'.
      • crlfDelay(number):如果\r与\n之间的延迟超过crlfDelay毫秒,则\r与\n都会当做换行分隔符。默认为100毫秒。crlfDelay的范围为[100,2000].
    • readline.createInterface()方法创建一个新的readline.Intreface实例,例子如下:
const readline=require('readline');
const rl=readline.createInterface({
  input:process.stdin,
  output:process.stdout
});
+ 一旦readline.Interface实例被创建,最常见的就是监听‘line’事件:
rl.on('line',(line)=>{
  console.log(`接收到:${line}`);
});
+ 如果该实例的terminal为true,则若它定义了一个output.columns属性则output流会获得最佳兼容性,且如果或当列发生变化时,output上触发一个'resize'事件(当它为一个TTY时,process.stdout会自动处理这个)。
+ completer函数使用:当被调用时,用户输入的当前行会被提供给completer函数,并返回一个包含以下两个条目的数组:
   + 一个包含自动补全输入的数组。
   + 用于匹配的字符串。
   + 例如:[[substr1,substr2,...],originalsubstring]。
function completer(line){
  const completions='.help .error .quit  .q'.split(' ');
  const hits=completions.filter((c)=>{return c.indexOf(line)==0});
  //如果没匹配到则展示到=全部补全
  return  [hits.length?hits:completions,line];
}
   + 如果completer函数结束两个参数,则可被异步地调用。
function completer(linePartial,callback){
  callback(null,[['123'],linePartial]);
}
  • readline.curorTo(stream,x,y):
    • stream(writable):
    • x (number):
    • y(number):
    • readline.cursorTo()方法会移动光标到指定的TTY stream中指定的位置。
  • readline.emitKeypressEvent(stream[,interface):
    • stream(Readable):
    • interface(readline.Interface):
    • readline.emitKeypressEvents()方法是给定的可写流stream相应接收到的输入触发‘keypress’事件。
    • 可选的interface指定了一个readline.Interface实例,用于当自动补全被禁用时检测到复制黏贴输入。
    • 如果stream是一个TTY,则它必须为原始模式。
readline.emitKeypressEvents(process.stdin);
if(process.stdin.isTTY)
  process.stdin.setRawMode(true);
  • readline.moveCursor(stream,dx,xy):
    • stream:(writable):
    • dx:(number):
    • dy(Number):
    • readline.moveCursor()方法移动光标到给定的TTY stream中相对当前的位置。
3.例子:简单的命令行界面
  • 例子,使用readline.Interface类实现一个简单的命令行界面:
const readline=require('readline');
const rl=readline.createInterface({
  input:process.stdin,
  output:process.stdout,
  prompt:'请输入>'
});
rl.prompt();
rl.on('line',(line)=>{
  switch(line.trim()){
    case 'hello':
      console.log('world');break;
    default:
      console.log(`你输入的是:${line.trim()}`);break;
  }
rl.prompt();
}).on('close',()=>{
  console.log('再见!');
  process.exit(0);
});
4.逐行读取文件流:
  • 例子,从一个文件系统可读流中每次一行地消耗输入:
const readline=require('readline');
const fs=require('fs');
const rl=readline.createInterface({
  input:fs.createReadStream('sample.txt');
});
rl.on('line',(line)=>{
  console.log('文件的单行内容:${line}');
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • 终端和nodejs的io交互(io是input和output,输入和输出) 终端和io交互需要引入一个nodejs...
    东海虬髯客阅读 274评论 0 0
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,305评论 0 6
  • 本课重点:学习使用Node.js中的'readline'模块实现终端的io交互功能,并衍生到web中静态页面上的i...
    疯范儿阅读 351评论 0 0
  • 个人入门学习用笔记、不过多作为参考依据。如有错误欢迎斧正 目录 简书好像不支持锚点、复制搜索(反正也是写给我自己看...
    kirito_song阅读 2,449评论 1 37