Node.js v25.0.0 文档
- Node.js v25.0.0
- 目录
-
索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲区
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入器 API
- 子进程
- 集群
- 命令行选项
- 控制台
- 加密
- 调试器
- 已弃用的 API
- 诊断通道
- DNS
- 域
- 环境变量
- 错误
- 事件
- 文件系统
- 全局对象
- HTTP
- HTTP/2
- HTTPS
- 检查器
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:包
- 模块:TypeScript
- 网络
- 操作系统
- 路径
- 性能钩子
- 权限
- 进程
- Punycode
- 查询字符串
- 逐行读取
- REPL
- 报告
- 单一可执行文件应用
- SQLite
- 流
- 字符串解码器
- 测试运行器
- 定时器
- TLS/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用工具
- V8
- 虚拟机
- WASI
- Web Crypto API
- Web Streams API
- 工作线程
- Zlib
- 其他版本
- 选项
Readline#
源代码: lib/readline.js
node:readline
模块提供了一个接口,用于从可读流(例如 process.stdin
)中一次一行地读取数据。
要使用基于 Promise 的 API
import * as readline from 'node:readline/promises';
const readline = require('node:readline/promises');
要使用回调和同步 API
import * as readline from 'node:readline';
const readline = require('node:readline');
以下简单示例说明了 node:readline
模块的基本用法。
import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
const rl = readline.createInterface({ input, output });
const answer = await rl.question('What do you think of Node.js? ');
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');
const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
});
一旦调用此代码,Node.js 应用程序将不会终止,直到 readline.Interface
被关闭,因为该接口会等待在 input
流上接收数据。
类:InterfaceConstructor
#
- 继承自:<EventEmitter>
InterfaceConstructor
类的实例是使用 readlinePromises.createInterface()
或 readline.createInterface()
方法构造的。每个实例都与一个 input
可读流和一个 output
可写流相关联。output
流用于为到达 input
流并从中读取的用户输入打印提示。
事件:'close'
#
当发生以下任一情况时,将触发 'close'
事件:
- 调用
rl.close()
方法,且InterfaceConstructor
实例已放弃对input
和output
流的控制; input
流接收到其'end'
事件;input
流接收到 Ctrl+D 来表示传输结束 (EOT);input
流接收到 Ctrl+C 来表示SIGINT
,并且InterfaceConstructor
实例上没有注册'SIGINT'
事件监听器。
调用监听器函数时不传递任何参数。
一旦发出 'close'
事件,InterfaceConstructor
实例就完成了。
事件:'line'
#
每当 input
流接收到行尾输入(\n
、\r
或 \r\n
)时,就会触发 'line'
事件。这通常在用户按下 Enter 键或 Return 键时发生。
如果从流中读取了新数据,并且该流在没有最终行尾标记的情况下结束,也会触发 'line'
事件。
监听器函数被调用时,会传入一个包含接收到的单行输入的字符串。
rl.on('line', (input) => {
console.log(`Received: ${input}`);
});
事件:'history'
#
每当历史记录数组发生变化时,就会触发 'history'
事件。
监听器函数被调用时,会传入一个包含历史记录数组的数组。它将反映所有更改,包括由于 historySize
和 removeHistoryDuplicates
而添加和删除的行。
其主要目的是允许监听器持久化历史记录。监听器也可以更改历史记录对象。这对于防止某些行(如密码)被添加到历史记录中很有用。
rl.on('history', (history) => {
console.log(`Received: ${history}`);
});
事件:'pause'
#
当发生以下任一情况时,将触发 'pause'
事件:
调用监听器函数时不传递任何参数。
rl.on('pause', () => {
console.log('Readline paused.');
});
事件:'resume'
#
每当 input
流恢复时,就会触发 'resume'
事件。
调用监听器函数时不传递任何参数。
rl.on('resume', () => {
console.log('Readline resumed.');
});
事件:'SIGCONT'
#
当一个 Node.js 进程先前使用 Ctrl+Z(即 SIGTSTP
)移至后台,然后使用 fg(1p)
重新带回前台时,会触发 'SIGCONT'
事件。
如果在 SIGTSTP
请求之前 input
流被暂停,则不会触发此事件。
调用监听器函数时不传递任何参数。
rl.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
rl.prompt();
});
'SIGCONT'
事件在 Windows 上不支持。
事件:'SIGINT'
#
当 input
流接收到 Ctrl+C 输入(通常称为 SIGINT
)时,会触发 'SIGINT'
事件。如果在 input
流接收到 SIGINT
时没有注册 'SIGINT'
事件监听器,则会触发 'pause'
事件。
调用监听器函数时不传递任何参数。
rl.on('SIGINT', () => {
rl.question('Are you sure you want to exit? ', (answer) => {
if (answer.match(/^y(es)?$/i)) rl.pause();
});
});
事件:'SIGTSTP'
#
当 input
流接收到 Ctrl+Z 输入(通常称为 SIGTSTP
)时,会触发 'SIGTSTP'
事件。如果在 input
流接收到 SIGTSTP
时没有注册 'SIGTSTP'
事件监听器,Node.js 进程将被发送到后台。
当使用 fg(1p)
恢复程序时,将触发 'pause'
和 'SIGCONT'
事件。这些事件可用于恢复 input
流。
如果进程被发送到后台之前 input
流已暂停,则不会触发 'pause'
和 'SIGCONT'
事件。
调用监听器函数时不传递任何参数。
rl.on('SIGTSTP', () => {
// This will override SIGTSTP and prevent the program from going to the
// background.
console.log('Caught SIGTSTP.');
});
'SIGTSTP'
事件在 Windows 上不支持。
rl.close()
#
rl.close()
方法关闭 InterfaceConstructor
实例并放弃对 input
和 output
流的控制。调用时,将触发 'close'
事件。
调用 rl.close()
不会立即停止由 InterfaceConstructor
实例触发的其他事件(包括 'line'
)。
rl[Symbol.dispose]()
#
rl.close()
的别名。
rl.pause()
#
rl.pause()
方法暂停 input
流,允许在必要时稍后恢复。
调用 rl.pause()
不会立即暂停由 InterfaceConstructor
实例触发的其他事件(包括 'line'
)。
rl.prompt([preserveCursor])
#
preserveCursor
<boolean> 如果为true
,则防止光标位置被重置为0
。
rl.prompt()
方法将 InterfaceConstructor
实例配置的 prompt
写入 output
的新行,以便为用户提供一个新的位置来输入。
调用时,如果 input
流已暂停,rl.prompt()
将恢复它。
如果创建 InterfaceConstructor
时将 output
设置为 null
或 undefined
,则不会写入提示。
rl.resume()
#
如果 input
流已暂停,rl.resume()
方法会恢复它。
rl.write(data[, key])
#
rl.write()
方法将 data
或由 key
标识的键序列写入 output
。仅当 output
是 TTY 文本终端时,才支持 key
参数。有关组合键的列表,请参见 TTY 快捷键绑定。
如果指定了 key
,则忽略 data
。
调用时,如果 input
流已暂停,rl.write()
将恢复它。
如果创建 InterfaceConstructor
时将 output
设置为 null
或 undefined
,则不会写入 data
和 key
。
rl.write('Delete this!');
// Simulate Ctrl+U to delete the line written previously
rl.write(null, { ctrl: true, name: 'u' });
rl.write()
方法将数据写入 readline
Interface
的 input
,就好像是用户提供的一样。
rl[Symbol.asyncIterator]()
#
创建一个 AsyncIterator
对象,该对象以字符串形式遍历输入流中的每一行。此方法允许通过 for await...of
循环对 InterfaceConstructor
对象进行异步迭代。
输入流中的错误不会被转发。
如果循环因 break
、throw
或 return
而终止,将调用 rl.close()
。换句话说,对 InterfaceConstructor
的迭代将始终完全消耗输入流。
性能不如传统的 'line'
事件 API。对于性能敏感的应用程序,请改用 'line'
。
async function processLineByLine() {
const rl = readline.createInterface({
// ...
});
for await (const line of rl) {
// Each line in the readline input will be successively available here as
// `line`.
}
}
readline.createInterface()
一旦调用就会开始消耗输入流。在接口创建和异步迭代之间进行异步操作可能会导致行丢失。
rl.line
#
- 类型:<string>
节点正在处理的当前输入数据。
当从 TTY 流收集输入时,可以使用此属性来检索在 line
事件触发之前已处理的当前值。一旦 line
事件被触发,此属性将成为一个空字符串。
请注意,如果在实例运行时修改该值而不同时控制 rl.cursor
,可能会产生意想不到的后果。
如果不使用 TTY 流进行输入,请使用 'line'
事件。
一个可能的用例如下:
const values = ['lorem ipsum', 'dolor sit amet'];
const rl = readline.createInterface(process.stdin);
const showResults = debounce(() => {
console.log(
'\n',
values.filter((val) => val.startsWith(rl.line)).join(' '),
);
}, 300);
process.stdin.on('keypress', (c, k) => {
showResults();
});
rl.cursor
#
- 类型:<number> | <undefined>
光标相对于 rl.line
的位置。
当从 TTY 流读取输入时,这将跟踪当前光标在输入字符串中的位置。光标的位置决定了在处理输入时将被修改的输入字符串部分,以及终端光标将呈现的列。
Promises API#
类:readlinePromises.Interface
#
readlinePromises.Interface
类的实例是使用 readlinePromises.createInterface()
方法构造的。每个实例都与一个 input
可读流和一个 output
可写流相关联。output
流用于为到达 input
流并从中读取的用户输入打印提示。
rl.question(query[, options])
#
query
<string> 要写入output
的语句或查询,前置于提示符。options
<Object>signal
<AbortSignal> 可选地允许使用AbortSignal
取消question()
。
- 返回:<Promise> 一个 Promise,它会在用户响应
query
的输入时被 fulfill。
rl.question()
方法通过将 query
写入 output
来显示它,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,如果 input
流已暂停,rl.question()
将恢复它。
如果创建 readlinePromises.Interface
时将 output
设置为 null
或 undefined
,则不会写入 query
。
如果在 rl.close()
之后调用此问题,它将返回一个被拒绝的 Promise。
用法示例:
const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`);
使用 AbortSignal
取消提问。
const signal = AbortSignal.timeout(10_000);
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
const answer = await rl.question('What is your favorite food? ', { signal });
console.log(`Oh, so your favorite food is ${answer}`);
类:readlinePromises.Readline
#
new readlinePromises.Readline(stream[, options])
#
stream
<stream.Writable> 一个 TTY 流。options
<Object>autoCommit
<boolean> 如果为true
,则无需调用rl.commit()
。
rl.clearLine(dir)
#
dir
<integer>-1
: 从光标向左1
: 从光标向右0
: 整行
- 返回:this
rl.clearLine()
方法向内部待处理操作列表添加一个操作,该操作以 dir
标识的指定方向清除关联 stream
的当前行。调用 rl.commit()
以查看此方法的效果,除非在构造函数中传递了 autoCommit: true
。
rl.clearScreenDown()
#
- 返回:this
rl.clearScreenDown()
方法向内部待处理操作列表添加一个操作,该操作从光标当前位置向下清除关联的流。调用 rl.commit()
以查看此方法的效果,除非在构造函数中传递了 autoCommit: true
。
rl.cursorTo(x[, y])
#
rl.cursorTo()
方法向内部待处理操作列表添加一个操作,该操作将光标移动到关联 stream
中的指定位置。调用 rl.commit()
以查看此方法的效果,除非在构造函数中传递了 autoCommit: true
。
rl.moveCursor(dx, dy)
#
rl.moveCursor()
方法向内部待处理操作列表添加一个操作,该操作将光标相对于其在关联 stream
中的当前位置进行移动。调用 rl.commit()
以查看此方法的效果,除非在构造函数中传递了 autoCommit: true
。
readlinePromises.createInterface(options)
#
options
<Object>input
<stream.Readable> 要监听的可读流。此选项是必需的。output
<stream.Writable> 要写入 readline 数据的可写流。completer
<Function> 一个可选函数,用于 Tab 自动补全。terminal
<boolean> 如果input
和output
流应被视为 TTY,并且应向其写入 ANSI/VT100 转义码,则为true
。默认值:在实例化时检查output
流的isTTY
。history
<string[]> 历史记录行的初始列表。此选项仅在用户或内部output
检查将terminal
设置为true
时才有意义,否则根本不会初始化历史记录缓存机制。默认值:[]
。historySize
<number> 保留的历史记录行的最大数量。要禁用历史记录,请将此值设置为0
。此选项仅在用户或内部output
检查将terminal
设置为true
时才有意义,否则根本不会初始化历史记录缓存机制。默认值:30
。removeHistoryDuplicates
<boolean> 如果为true
,当添加到历史记录列表的新输入行与旧行重复时,将从列表中删除旧行。默认值:false
。prompt
<string> 要使用的提示字符串。默认值:'> '
。crlfDelay
<number> 如果\r
和\n
之间的延迟超过crlfDelay
毫秒,则\r
和\n
都将被视为单独的行尾输入。crlfDelay
将被强制转换为不小于100
的数字。它可以设置为Infinity
,在这种情况下,\r
后跟\n
将始终被视为单个换行符(这对于读取具有\r\n
行分隔符的文件可能是合理的)。默认值:100
。escapeCodeTimeout
<number>readlinePromises
将等待一个字符的持续时间(以毫秒为单位,当读取一个模糊的键序列时,该序列既可以使用目前为止读取的输入形成一个完整的键序列,也可以接受额外的输入来完成一个更长的键序列)。默认值:500
。tabSize
<integer> 一个制表符等于的空格数(最小为 1)。默认值:8
。signal
<AbortSignal> 允许使用 AbortSignal 关闭接口。
- 返回:<readlinePromises.Interface>
readlinePromises.createInterface()
方法创建一个新的 readlinePromises.Interface
实例。
import { createInterface } from 'node:readline/promises';
import { stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: stdout,
});
const { createInterface } = require('node:readline/promises');
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
一旦创建了 readlinePromises.Interface
实例,最常见的情况是监听 'line'
事件:
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
如果此实例的 terminal
为 true
,那么如果 output
流定义了 output.columns
属性并在列数发生变化时在 output
上触发 'resize'
事件(当 process.stdout
是 TTY 时会自动执行此操作),则 output
流将获得最佳兼容性。
completer
函数的用法#
completer
函数将用户输入的当前行作为参数,并返回一个包含 2 个条目的 Array
:
- 一个包含匹配补全条目的
Array
。 - 用于匹配的子字符串。
例如:[[substr1, substr2, ...], originalsubstring]
。
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
}
completer
函数也可以返回一个 <Promise>,或者可以是异步的:
async function completer(linePartial) {
await someAsyncWork();
return [['123'], linePartial];
}
回调 API#
类:readline.Interface
#
readline.Interface
类的实例是使用 readline.createInterface()
方法构造的。每个实例都与一个 input
可读流和一个 output
可写流相关联。output
流用于为到达 input
流并从中读取的用户输入打印提示。
rl.question(query[, options], callback)
#
query
<string> 要写入output
的语句或查询,前置于提示符。options
<Object>signal
<AbortSignal> 可选地允许使用AbortController
取消question()
。
callback
<Function> 一个回调函数,在用户响应query
的输入时被调用。
rl.question()
方法通过将 query
写入 output
来显示它,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,如果 input
流已暂停,rl.question()
将恢复它。
如果创建 readline.Interface
时将 output
设置为 null
或 undefined
,则不会写入 query
。
传递给 rl.question()
的 callback
函数不遵循接受 Error
对象或 null
作为第一个参数的典型模式。该 callback
被调用时,只传入提供的答案作为唯一参数。
如果在 rl.close()
之后调用 rl.question()
,将会抛出一个错误。
用法示例:
rl.question('What is your favorite food? ', (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
使用 AbortController
取消提问。
const ac = new AbortController();
const signal = ac.signal;
rl.question('What is your favorite food? ', { signal }, (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
setTimeout(() => ac.abort(), 10000);
readline.clearLine(stream, dir[, callback])
#
stream
<stream.Writable>dir
<number>-1
: 从光标向左1
: 从光标向右0
: 整行
callback
<Function> 操作完成后调用。- 返回:<boolean> 如果
stream
希望调用代码在继续写入额外数据之前等待'drain'
事件触发,则为false
;否则为true
。
readline.clearLine()
方法以 dir
标识的指定方向清除给定的 TTY 流的当前行。
readline.clearScreenDown(stream[, callback])
#
stream
<stream.Writable>callback
<Function> 操作完成后调用。- 返回:<boolean> 如果
stream
希望调用代码在继续写入额外数据之前等待'drain'
事件触发,则为false
;否则为true
。
readline.clearScreenDown()
方法从光标当前位置向下清除给定的 TTY 流。
readline.createInterface(options)
#
options
<Object>input
<stream.Readable> 要监听的可读流。此选项是必需的。output
<stream.Writable> 要写入 readline 数据的可写流。completer
<Function> 一个可选函数,用于 Tab 自动补全。terminal
<boolean> 如果input
和output
流应被视为 TTY,并且应向其写入 ANSI/VT100 转义码,则为true
。默认值:在实例化时检查output
流的isTTY
。history
<string[]> 历史记录行的初始列表。此选项仅在用户或内部output
检查将terminal
设置为true
时才有意义,否则根本不会初始化历史记录缓存机制。默认值:[]
。historySize
<number> 保留的历史记录行的最大数量。要禁用历史记录,请将此值设置为0
。此选项仅在用户或内部output
检查将terminal
设置为true
时才有意义,否则根本不会初始化历史记录缓存机制。默认值:30
。removeHistoryDuplicates
<boolean> 如果为true
,当添加到历史记录列表的新输入行与旧行重复时,将从列表中删除旧行。默认值:false
。prompt
<string> 要使用的提示字符串。默认值:'> '
。crlfDelay
<number> 如果\r
和\n
之间的延迟超过crlfDelay
毫秒,则\r
和\n
都将被视为单独的行尾输入。crlfDelay
将被强制转换为不小于100
的数字。它可以设置为Infinity
,在这种情况下,\r
后跟\n
将始终被视为单个换行符(这对于读取具有\r\n
行分隔符的文件可能是合理的)。默认值:100
。escapeCodeTimeout
<number>readline
将等待一个字符的持续时间(以毫秒为单位,当读取一个模糊的键序列时,该序列既可以使用目前为止读取的输入形成一个完整的键序列,也可以接受额外的输入来完成一个更长的键序列)。默认值:500
。tabSize
<integer> 一个制表符等于的空格数(最小为 1)。默认值:8
。signal
<AbortSignal> 允许使用 AbortSignal 关闭接口。中止信号将在内部调用接口上的close
。
- 返回:<readline.Interface>
readline.createInterface()
方法创建一个新的 readline.Interface
实例。
import { createInterface } from 'node:readline';
import { stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: stdout,
});
const { createInterface } = require('node:readline');
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
一旦创建了 readline.Interface
实例,最常见的情况是监听 'line'
事件:
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
如果此实例的 terminal
为 true
,那么如果 output
流定义了 output.columns
属性并在列数发生变化时在 output
上触发 'resize'
事件(当 process.stdout
是 TTY 时会自动执行此操作),则 output
流将获得最佳兼容性。
当使用 stdin
作为输入创建 readline.Interface
时,程序在收到 EOF 字符之前不会终止。要不等待用户输入就退出,请调用 process.stdin.unref()
。
completer
函数的用法#
completer
函数将用户输入的当前行作为参数,并返回一个包含 2 个条目的 Array
:
- 一个包含匹配补全条目的
Array
。 - 用于匹配的子字符串。
例如:[[substr1, substr2, ...], originalsubstring]
。
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
}
如果 completer
函数接受两个参数,则可以异步调用它:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
}
readline.cursorTo(stream, x[, y][, callback])
#
stream
<stream.Writable>x
<number>y
<number>callback
<Function> 操作完成后调用。- 返回:<boolean> 如果
stream
希望调用代码在继续写入额外数据之前等待'drain'
事件触发,则为false
;否则为true
。
readline.cursorTo()
方法将光标移动到给定的 TTY stream
中的指定位置。
readline.moveCursor(stream, dx, dy[, callback])
#
stream
<stream.Writable>dx
<number>dy
<number>callback
<Function> 操作完成后调用。- 返回:<boolean> 如果
stream
希望调用代码在继续写入额外数据之前等待'drain'
事件触发,则为false
;否则为true
。
readline.moveCursor()
方法将光标相对于其在给定的 TTY stream
中的当前位置进行移动。
readline.emitKeypressEvents(stream[, interface])
#
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
readline.emitKeypressEvents()
方法使给定的可读流开始触发与接收到的输入相对应的 'keypress'
事件。
可选地,interface
指定一个 readline.Interface
实例,当检测到复制粘贴的输入时,将为其禁用自动补全。
如果 stream
是一个 TTY,那么它必须处于原始模式。
如果 input
是一个终端,任何 readline 实例都会在其 input
上自动调用此方法。关闭 readline
实例不会停止 input
触发 'keypress'
事件。
readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY)
process.stdin.setRawMode(true);
示例:微型 CLI#
以下示例说明了如何使用 readline.Interface
类来实现一个小型命令行界面:
import { createInterface } from 'node:readline';
import { exit, stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: stdout,
prompt: 'OHAI> ',
});
rl.prompt();
rl.on('line', (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', () => {
console.log('Have a great day!');
exit(0);
});
const { createInterface } = require('node:readline');
const rl = createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'OHAI> ',
});
rl.prompt();
rl.on('line', (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', () => {
console.log('Have a great day!');
process.exit(0);
});
示例:逐行读取文件流#
readline
的一个常见用例是逐行消费一个输入文件。最简单的方法是利用 fs.ReadStream
API 以及 for await...of
循环:
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
async function processLineByLine() {
const fileStream = createReadStream('input.txt');
const rl = createInterface({
input: fileStream,
crlfDelay: Infinity,
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
async function processLineByLine() {
const fileStream = createReadStream('input.txt');
const rl = createInterface({
input: fileStream,
crlfDelay: Infinity,
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
或者,可以使用 'line'
事件:
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});
目前,for await...of
循环可能会慢一些。如果 async
/ await
流程和速度都至关重要,可以采用混合方法:
import { once } from 'node:events';
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
// Process the line.
});
await once(rl, 'close');
console.log('File processed.');
} catch (err) {
console.error(err);
}
})();
const { once } = require('node:events');
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
// Process the line.
});
await once(rl, 'close');
console.log('File processed.');
} catch (err) {
console.error(err);
}
})();
TTY 快捷键绑定#
快捷键 | 描述 | 注意 |
---|---|---|
Ctrl+Shift+Backspace | 删除左侧行 | 在 Linux、Mac 和 Windows 上无效 |
Ctrl+Shift+Delete | 删除右侧行 | 在 Mac 上无效 |
Ctrl+C | 触发 SIGINT 或关闭 readline 实例 |
|
Ctrl+H | 向左删除 | |
Ctrl+D | 向右删除,或在当前行空/EOF时关闭 readline 实例 | 在 Windows 上无效 |
Ctrl+U | 从当前位置删除到行首 | |
Ctrl+K | 从当前位置删除到行尾 | |
Ctrl+Y | 粘贴(恢复)之前删除的文本 | 仅对通过 Ctrl+U 或 Ctrl+K 删除的文本有效 |
Meta+Y | 在先前删除的文本之间循环 | 仅在最后一次按键是 Ctrl+Y 或 Meta+Y 时可用 |
Ctrl+A | 移动到行首 | |
Ctrl+E | 移动到行尾 | |
Ctrl+B | 后退一个字符 | |
Ctrl+F | 前进一个字符 | |
Ctrl+L | 清屏 | |
Ctrl+N | 下一个历史记录项 | |
Ctrl+P | 上一个历史记录项 | |
Ctrl+- | 撤销上一次更改 | 任何发出键码 0x1F 的按键都会执行此操作。在许多终端(例如 xterm )中,这被绑定到 Ctrl+-。 |
Ctrl+6 | 重做上一次更改 | 许多终端没有默认的重做快捷键。我们选择键码 0x1E 来执行重做。在 xterm 中,它默认绑定到 Ctrl+6。 |
Ctrl+Z | 将正在运行的进程移至后台。输入 fg 并按 Enter 返回。 |
在 Windows 上无效 |
Ctrl+W 或 Ctrl +Backspace | 向后删除到单词边界 | Ctrl+Backspace 在 Linux、Mac 和 Windows 上无效 |
Ctrl+Delete | 向前删除到单词边界 | 在 Mac 上无效 |
Ctrl+Left arrow 或 Meta+B | 向左移动一个单词 | Ctrl+Left arrow 在 Mac 上无效 |
Ctrl+Right arrow 或 Meta+F | 向右移动一个单词 | Ctrl+Right arrow 在 Mac 上无效 |
Meta+D 或 Meta +Delete | 向右删除一个单词 | Meta+Delete 在 Windows 上无效 |
Meta+Backspace | 向左删除一个单词 | 在 Mac 上无效 |