关于readline
readline是Node.js中实现控制台输入输出的模块,而通过模块的接口我们可以实现逐行读取输入流,类似Java中的Scanner。
使用readline
在使用readline之前我们需要对readline中Interface类的 close事件 与 line事件 有个简单的认识。
一、‘line’ 事件:
当输入流接收到行结束符 ("\n","\r",或者"\r\n") 时则触发line事件,一般情况下会在用户按下【Enter】回车键后触发 (在Mac中则是【Return】键) ,当该事件被调用时,监听器函数则会返还在控制台输入的这一行字符串。
举例:
//导入readline模块
var readline = require('readline');
//创建readline.Interface实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
//line事件
readlineTest.on('line', function(line){
console.log("您输入了:"+line);
r1.close();
});
//close事件
readlineTest.on('close', function() {
process.exit(0);
});
当在控制台输入 ‘Hello’ ,则控制台输出 您输入了:Hello 。
注意:此时若没有使用close事件,则程序不会结束。
二、‘close’ 事件:
以下是Node.js官方API文档对于close事件的介绍,一句话概括的话就是:
当readline.Interface实例执行close事件后,readline.Interface实例就会结束。
例如,创建一个readline.Interface实例,并调用 ‘line’ 事件,若没有调用close事件,则程序调用的’line’事件不会结束,而当close事件被调用时,readline.Interface实例才会结束。
readline实现单行输入与输出
具体代码模块如下:
//导入readline模块
var readline = require('readline');
//创建readline.Interface实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
//line事件
readlineTest.on('line', function(temp){
//代码块
readlineTest.close();//使readline.Interface实例结束
});
//close事件
readlineTest.on('close', function() {
process.exit(0);
});
首先我们需要导入readline模块,接着创建一个readline.Interface实例,随后调用line事件等待输入信息,接收到输入信息temp后运行代码块,再接着执行close事件结束readline.Interface实例。
实例1 实现a+b=c
//导入readline模块
var readline = require('readline');
//创建readline.Interface实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
//创建一个空数组来存储控制台输入的内容
var numberArray=[];
//初始化结果值
var result=0;
//line事件
readlineTest.on('line', function(line){
//将控制台输入内容去前后空格和换行符,再按空格分割,形成一个新数组,并且赋给数组numberArray
numberArray=line.trim().split(" ");
//通过遍历将数组元素中可以转换为数值的元素转换为number类型
for(var i in numberArray){
numberArray[i]=Number(numberArray[i]);
}
//将数组元素叠加后的值赋值给result
result=numberArray.reduce(function(total,next){
return total+next;
},0);
//打印输出
console.log(numberArray[0]+" + "+numberArray[1]+" = "+result);
readlineTest.close();//使readline.Interface实例结束
});
//close事件
readlineTest.on('close', function() {
process.exit(0);
});
控制台输入格式:
Example: 10 20
数字之间用一个空格隔开
运行截图:
此处line事件亦可替换为question事件,关于question事件由于笔者未深入了解,若有需要请跳转至node.js官方API文档查看详细说明。
node.js官方API文档-question事件: http://nodejs.cn/api/readline.html#readline_rl_question_query_callback
readline实现多行输入操作
(1)参数写死的多行输入
具体模板如下:
// 引入readline模块
var readline = require('readline');
// 创建一个readline接口实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var lineCounts=4;//输入的行数,参数写死
var tempArray=[];//创建数组来存储每一行的数据
var tempArrayIndex=0;//初始化数组的索引
readlineTest.on('line', function(line){
//将每一行的内容添加至数组tempArray
tempArray[tempArrayIndex]=line;
tempArrayIndex++;
//当已输入的行数达到最大输入的行数时,结束readline.Interface实例
if(tempArray.length==lineCounts){
console.log(tempArray);//用于调试,可删去
readlineTest.close();
}
});
//当readlineTest执行'close'命令时,输入流关闭,程序结束。
readlineTest.on('close', function() {
process.exit(0);
});
首先,代码中的lineCounts表示写死的行数,例如,若想输入3行,则将lineCounts的值设为3。已知line事件返回的line为在控制台输入的内容,并且是以String形式返还。我们将line写入空数组,当需要处理控制台输入的元素时,则调用数组中相应的元素。当数组的长度等于lineCounts,那么说明输入的行数已经到达最大,此时则结束readline.Interface实例。
实例:多行输入 a+b=c
// 引入readline模块
var readline = require('readline');
// 创建一个readline接口实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var numberArray=[];//创建数值数组来存储每一行的数据
var numberArrayIndex=0;//初始化数值数组的索引
var lineCounts=4;//输入的行数,参数写死
var result=0;//初始化结果值
var str="";//整合式子
readlineTest.on('line', function(line){
//将每一行的内容转换为数字后添加至数值数组numberArray
numberArray[numberArrayIndex]=Number(line);
numberArrayIndex++;
//将数组每个元素叠加后赋值给result
result=numberArray.reduce(function(total,nextTemp){
return total+nextTemp;
},0);
//当已输入的行数达到最大输入的行数时,结束readline.Interface实例
if(numberArray.length==lineCounts){
//组合式子
for(var i in numberArray){
if(i==numberArray.length-1){
str+=numberArray[i]+"="+result;
}else{
str+=numberArray[i]+"+";
}
}
//打印结果式子
console.log(str);
readlineTest.close();
}
});
//当readlineTest执行'close'命令时,输入流关闭,程序结束。
readlineTest.on('close', function() {
process.exit(0);
});
运行效果图:
标注:这里我将lineCounts设定为4
缺点:参数写死
参数写死对于用代码的人是非常不方便的,因此不推荐这种做法,这里笔者只是以案例介绍这种多行输入的方法,每次用代码都得修改代码中的变量是一件非常没有效率的事情。
(2)控制台自定义行数
想法:将控制台输入的第一行的值作为接下来控制台还可输入的行数,将接下来控制台输入的内容写入新的数组,方便代码块处理。
具体模板代码:
// 引入readline模块
var readline = require('readline');
// 创建一个readline接口实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var linesArray=[];//该数组用来存储输入的内容
var linesArrayIndex=0;//设置存储输入内容数组的索引初始值
var resultArray=[];//该数组用来存储除输入内容第一行外其他行的输入内容
readlineTest.on('line', function(line){
//将存储输入内容的数组linesArray的第一个元素linesArray[0]的值设置为允许输入的行数
if(linesArrayIndex==0){
linesArray[linesArrayIndex]=Number(line);
//打印控制台输入的第一行内容:"允许输入的行数"
console.log("允许输入的行数: "+linesArray[0]);
}
//将每一行的内容作为一个单元写入数组linesArray,并且每写入一个元素则数组下标linesArrayIndex自增1
linesArray[linesArrayIndex]=line;
linesArrayIndex++;
//调用Array对象的slice()方法返回linesArray数组的子数组(该子数组的内容为: 除linesArray数组第一个元素外的其他元素)
//将子数组的每个元素依次添加至结果数组resultArray
for(var i in linesArray.slice(1)){
resultArray[i]=linesArray.slice(1)[i];
}
//当输入内容的行数等于linesArray数组的第一个元素(即允许输入的行数)时,则关闭输入流readline
if(resultArray.length==linesArray[0]){
//打印输出整合在数组resultArray中的输入内容
console.log(resultArray);
readlineTest.close();//关闭输入流
}
});
//当readlineTest执行'close'命令时,输入流关闭,程序结束。
readlineTest.on('close', function() {
process.exit(0);
});
模板运行实例:
如图,笔者在控制台输入数值 5,随后控制台允许输入5行内容,待5行内容输入完毕,按下回车后,结果数组打印输出。
流程实现:
首先,将第一行输入内容设定为接下来控制台允许输入的行数,已知linesArray数组用来存储控制台输入的每一行内容,而所需的内容则是除了第一个元素外的其他元素,因此,for in 循环用来为结果数组resultArray依次添加linesArray的子数组中的每个元素,也就是 linesArray.slice(1)后得到的linesArray子数组(注意:Array对象的slice()方法执行后不改变原数组,但linesArray.slice(1)代表的是除去第一个元素后的linesArray数组),最后判断设定行数后输入的行数是否等于linesArray数组第一个元素,若等于则结束readline.Interface实例。
实例:自定义行数多行输入 a+b=c
// 引入readline模块
var readline = require('readline');
// 创建一个readline接口实例
var readlineTest = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var linesArray=[];//该数组用来存储输入的内容
var linesArrayIndex=0;//设置存储输入内容数组的索引初始值
var resultArray=[];//该数组用来存储除输入内容第一行外其他行的输入内容
var result=0;//总值
var str=""//整合式子
readlineTest.on('line', function(line){
//将存储输入内容的数组linesArray的第一个元素linesArray[0]的值设置为允许输入的行数
if(linesArrayIndex==0){
linesArray[linesArrayIndex]=Number(line);
//打印控制台输入的第一行内容:"允许输入的行数"
console.log("允许输入的行数: "+linesArray[0]);
}
//将每一行的内容作为一个单元写入数组linesArray,并且每写入一个元素则数组下标linesArrayIndex自增1
linesArray[linesArrayIndex]=Number(line);
linesArrayIndex++;
//调用Array对象的slice()方法返回linesArray数组的子数组(该子数组的内容为: 除linesArray数组第一个元素外的其他元素)
//将子数组的每个元素依次添加至结果数组resultArray
for(var i in linesArray.slice(1)){
resultArray[i]=linesArray.slice(1)[i];
}
//将resultArray数组的元素叠加后的值赋值给result
result=resultArray.reduce(function(total,nextTemp){
return total+nextTemp;
},0);
//当输入内容的行数减一后等于linesArray数组的第一个元素(即允许输入的行数)时,则关闭输入流readline
if(resultArray.length==linesArray[0]){
//整合式子
for(var i in resultArray){
if(i==resultArray.length-1){
str+=resultArray[i]+"="+result;
}else{
str+=resultArray[i]+"+";
}
}
//打印输出整合后的式子
console.log(str);
readlineTest.close();//关闭输入流
}
});
//当readlineTest执行'close'命令时,输入流关闭,程序结束。
readlineTest.on('close', function() {
process.exit(0);
});
运行截图:
缺点:该方法不够灵活。
虽然能够自定义设置之后输入的行数,但是代码还是不够简洁明了,而且这两种多行输入的方法笔者认为有点傻瓜式,笔者也尝试了多个readline.Interface实例,也就是由一个readline.Interface实例来唤醒其他readline.Interface实例,由于能力有限,代码没写出来。
顺带一提,笔者的代码是基于 node.js10.11 版的,旧版本没有尝试是否能够运行,这里笔者希望如果读者有更好的代码不妨与笔者分享,笔者想更深入学习,亦或读者有何建议也欢迎私信笔者或者留言在评论区,并且本文也参考了一些资料与API文档,相关链接将在文末补全,以上案例和模板都将在blog发布后上传至Github和百度云盘,综上。
源代码:
1.Github
https://github.com/Viviendennis/Aika/tree/master/Readline单多行输入简单运用
由于我是第一次Github,并不知道如何分享文件链接,就直接复制链接过来了,后续更改吧。
2.百度云盘
参考的资料与API文档
(顺序无关轻重)
1.博主zgljl2012的
【Node.js基础篇】(九)使用readline模块实现Node.js的输入输出
2.博主KatherineLYP的
JavaScript - nodejs在线编程题获取控制台输入
3.Node.js官方API文档中关于readline的介绍:
4.W3school网站的JavaScript教程
5.MDN上的JavaScript技术文档: