Node.js v24.0.0 文档
- Node.js v24.0.0
- 目录
-
索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- Buffer
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入器 API
- 子进程
- 集群
- 命令行选项
- 控制台
- 密码学
- 调试器
- 已弃用的 API
- 诊断通道
- DNS
- 域
- 错误
- 事件
- 文件系统
- 全局对象
- HTTP
- HTTP/2
- HTTPS
- 检查器
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:包
- 模块:TypeScript
- Net
- 操作系统
- 路径
- 性能钩子
- 权限
- 进程
- Punycode
- 查询字符串
- Readline
- REPL
- 报告
- 单个可执行应用程序
- SQLite
- 流
- 字符串解码器
- 测试运行器
- 定时器
- TLS/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用工具
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作线程
- Zlib
- 其他版本
- 选项
Readline#
源代码: lib/readline.js
node:readline
模块提供了一个接口,用于从 Readable 流(例如 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
Readable 流和单个 output
Writable 流关联。 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'
#
当之前使用 Ctrl+Z(即 SIGTSTP
)移到后台的 Node.js 进程然后使用 fg(1p)
带回前台时,会触发 'SIGCONT'
事件。
如果 input
流在 SIGTSTP
请求之前暂停,则不会触发此事件。
调用监听器函数时不传递任何参数。
rl.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
rl.prompt();
});
Windows 上不支持 'SIGCONT'
事件。
事件:'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.');
});
Windows 上不支持 'SIGTSTP'
事件。
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()
将恢复该流。
如果使用设置为 null
或 undefined
的 output
创建了 InterfaceConstructor
,则不会写入提示符。
rl.resume()
#
如果 input
流已暂停,则 rl.resume()
方法会恢复该流。
rl.write(data[, key])
#
rl.write()
方法会将 data
或 key
标识的键序列写入到 output
。 仅当 output
是 TTY 文本终端时,才支持 key
参数。 有关键组合的列表,请参见 TTY 键绑定。
如果指定了 key
,则忽略 data
。
调用时,如果 input
流已暂停,则 rl.write()
将恢复该流。
如果使用将 output
设置为 null
或 undefined
创建了 InterfaceConstructor
,则不会写入 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>
创建一个 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
#
节点正在处理的当前输入数据。
这可以在从 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
#
相对于 rl.line
的光标位置。
当从 TTY 流读取输入时,这将跟踪当前光标在输入字符串中的位置。 光标的位置确定了在处理输入时将修改的输入字符串的部分,以及将呈现终端插入符的列。
Promises API#
类: readlinePromises.Interface
#
readlinePromises.Interface
类的实例使用 readlinePromises.createInterface()
方法构造。 每个实例都与单个 input
Readable 流和单个 output
Writable 流相关联。 output
流用于打印提示符,以提示用户在 input
流上到达并从该流读取的输入。
rl.question(query[, options])
#
query
<string> 要写入到output
的语句或查询,添加到提示符之前。options
<Object>signal
<AbortSignal> 可选地允许使用AbortSignal
取消question()
。
- 返回值: <Promise> 一个 promise,它将以用户响应
query
的输入来实现。
rl.question()
方法通过将其写入 output
来显示 query
,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,如果 input
流已暂停,则 rl.question()
将恢复该流。
如果使用将 output
设置为 null
或 undefined
创建了 readlinePromises.Interface
,则不会写入 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> 要监听的 Readable 流。此选项为必需。output
<stream.Writable> 用于将 readline 数据写入的 Writable 流。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
。
- 返回:<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 时会自动执行此操作),则该流将获得最佳兼容性。
使用 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
Readable 流和单个 output
Writable 流相关联。 output
流用于打印用户输入的提示,这些提示到达并从 input
流中读取。
rl.question(query[, options], callback)
#
query
<string> 要写入到output
的语句或查询,添加到提示符之前。options
<Object>signal
<AbortSignal> (可选)允许使用AbortController
取消question()
。
callback
<Function> (函数) 一个回调函数,该函数被调用,并将用户的输入作为对query
的响应。
rl.question()
方法通过将其写入 output
来显示 query
,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,如果 input
流已暂停,则 rl.question()
将恢复该流。
如果使用 output
设置为 null
或 undefined
创建了 readline.Interface
,则不写入 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()
方法清除给定 TTY 流中由 dir
标识的指定方向的当前行。
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> 要监听的 Readable 流。此选项为必需。output
<stream.Writable> 用于将 readline 数据写入的 Writable 流。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 时会自动执行此操作),则该流将获得最佳兼容性。
当使用 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()
方法使给定的 Readable 流开始发出与接收到的输入相对应的 '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 | Yank(调用)先前删除的文本 | 仅适用于由 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 上不起作用 |