---
url: https://sugarat.top/bigWeb/node/p1.md
---

# 使用Node.js从终端读入内容

## 前言

平时在写练习算法题的时，遇到线上笔试时，大部分在线练题网站都需要自己写输入输出，如常见的`牛客`，`赛码网`。部分不熟悉Node.js输入输出的朋友，就会感到有力无处使

通常此类网站是会直接提供一个`readline`或者`read_line`方法用来实现数据录入

实际上`Node`也是提供了一个模块[readline：逐行读取](http://nodejs.cn/api/readline.html)来实现此功能的

:::tip
笔者用过的练题网站只有[leetcode](https://leetcode-cn.com/)在使用js书写时只需要实现功能函数就行,就不需要考虑如何从键盘录入内容
:::

本文就和大家分享一下利用Node-readline模块实现通过终端中录入内容

## 简单使用

```js
const readline = require('readline')

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

// 不换行输出
process.stdout.write('请输入两个数字：')
// 监听键入回车事件
rl.on('line', (str) => {
    // str即为输入的内容
    
    const [a, b] = str.split(' ')
    console.log('和为：', (+a) + (+b));
    
    // 关闭逐行读取流 会触发关闭事件
    rl.close()
})

// 监听关闭事件
rl.on('close', () => {
    console.log('触发了关闭事件');
})
```

代码逻辑为：

* 输入两个数字
* 计算这两数字的和

假设上面的文件叫`index.js`,接下来我们直接输入下面运行

```sh
node index.js
```

运行结果如下:

![图片](https://img.cdn.sugarat.top/mdImg/MTYyMzk0Mjk3MDI0NQ==623942970245)

感觉并没有其它语言用起来那么安逸,比如:

* C++:`cin>>param`
* C:`scanf("%s",&param)`
* C#:`param = Console.ReadLine()`
* ...等等

怎样才能让Node.js从终端中录入数据变得像上述语言一样简单呢？

我们用动动自己的手指封装一下

## 封装

```js
const rdl = require('readline')

/**
 * 读入一行
 */
function readline() {
    const rl = rdl.createInterface({
        input: process.stdin,
        output: process.stdout
    })
    return new Promise(resolve => {
        rl.on('line', (str) => {
            resolve(str)
            rl.close()
        })
    })
}

module.exports = readline
```

我们在编写一个新的`test.js`,上面的叫`read.js` 放在同一目录下

```js
const readline = require('./readline')

async function main(){
    process.stdout.write('第一个单词：')
    const a = await readline()
    process.stdout.write('第二个单词：')
    const b = await readline()
    console.log(a , b);
}

main()
```

```js
node test.js
```

运行结果

![图片](https://img.cdn.sugarat.top/mdImg/MTYyMzk0Mzc3OTQ0OA==623943779448)

现在用起来就方便多了,已经有一点其它语言的味道了

## 其它工具方法封装

util.js

### print

不自动换行的打印方法

```js
function print(str){
    process.stdout.write(str)
}
```

使用:

```js
print('hello world\n')
print('666\n')
```

### readNumber

读取一个数字，因为`readline`读取的所有内容都是字符串的形式，读取数字的话需要自己做转换

```js
const readline = require('./readline')

async function readNumber(){
    return +(await readline())
}
```

测试：

```js
async function main(){
    const a = await readline()
    const b = await readNumber()

    console.log('a',typeof a);
    console.log('b',typeof b);
}

main()
```

运行结果

![图片](https://img.cdn.sugarat.top/mdImg/MTYyMzk0NDQ0MzAzNg==623944443036)

## 方法汇总

咱可以创建一个 **index.js**文件，然后将`readline`，`readNumber`，`print`三个方法统一对外导出：最终如下

```js
const rdl = require('readline')

function print(str){
    process.stdout.write(str)
}

/**
 * 读入一行
 */
function readline() {
    const rl = rdl.createInterface({
        input: process.stdin,
        output: process.stdout
    })
    return new Promise(resolve => {
        rl.on('line', (str) => {
            resolve(str)
            rl.close()
        })
    })
}


async function readNumber(){
    return +(await readline())
}


module.exports = {
    print,
    readline,
    readNumber
}
```

## 资料汇总

* [readline模块：逐行读取](http://nodejs.cn/api/readline.html)
* [demo源码](https://github.com/ATQQ/demos/tree/main/readline)
