Node.js v21.7.2 文档
- Node.js v21.7.2
- ► 目录
-
► 索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲区
- C++ 附加模块
- 使用 Node-API 的 C/C++ 附加模块
- C++ 嵌入器 API
- 子进程
- 集群
- 命令行选项
- 控制台
- Corepack
- 加密
- 调试器
- 已弃用的 API
- 诊断通道
- DNS
- 域
- 错误
- 事件
- 文件系统
- 全局对象
- HTTP
- HTTP/2
- HTTPS
- 检查器
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:包
- 网络
- 操作系统
- 路径
- 性能钩子
- 权限
- 进程
- Punycode
- 查询字符串
- Readline
- REPL
- 报告
- 单一可执行应用程序
- 流
- 字符串解码器
- 测试运行器
- 计时器
- TLS/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用工具
- V8
- VM
- 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
#
InterfaceConstructor
类实例是使用 readlinePromises.createInterface()
或 readline.createInterface()
方法构造的。每个实例都与一个 input
可读 流和一个 output
可写 流相关联。output
流用于打印用户输入的提示,这些提示来自 input
流并从 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();
});
'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.pause()
#
rl.pause()
方法会暂停 input
流,允许在需要时恢复。
调用 rl.pause()
不会立即暂停其他事件(包括 'line'
)从 InterfaceConstructor
实例发出。
rl.prompt([preserveCursor])
#
preserveCursor
<boolean> 如果为true
,则防止光标位置重置为0
。
rl.prompt()
方法将 InterfaceConstructor
实例配置的 prompt
写入 output
中的新行,以便为用户提供一个新的位置来输入。
调用 rl.prompt()
时,如果 input
流已暂停,则会恢复该流。
如果 InterfaceConstructor
是使用 output
设置为 null
或 undefined
创建的,则不会写入提示。
rl.resume()
#
rl.resume()
方法会恢复 input
流,如果它已被暂停。
rl.setPrompt(prompt)
#
prompt
<string>
rl.setPrompt()
方法设置每次调用 rl.prompt()
时将写入 output
的提示。
rl.getPrompt()
#
- 返回:<string> 当前提示字符串
rl.getPrompt()
方法返回 rl.prompt()
使用的当前提示。
rl.write(data[, key])
#
rl.write()
方法将 data
或由 key
标识的键序列写入 output
。key
参数仅在 output
为 TTY 文本终端时才受支持。有关键组合列表,请参见 TTY 键绑定。
如果指定了 key
,则忽略 data
。
调用时,rl.write()
将恢复 input
流(如果它已被暂停)。
如果 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
#
节点正在处理的当前输入数据。
当从 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 流读取输入时,这将跟踪当前光标在输入字符串中的位置。光标的位置决定了在处理输入时将修改的输入字符串部分,以及终端插入符号将呈现的列。
rl.getCursorPos()
#
返回光标相对于输入提示 + 字符串的实际位置。长输入(换行)字符串以及多行提示都包含在计算中。
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> 一个承诺,在用户对
query
的输入响应时,该承诺将被履行。
rl.question()
方法通过将 query
写入 output
来显示它,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,rl.question()
将恢复 input
流,如果它已被暂停。
如果 readlinePromises.Interface
是使用 output
设置为 null
或 undefined
创建的,则不会写入 query
。
如果在 rl.close()
之后调用该问题,它将返回一个被拒绝的承诺。
示例用法
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()
方法将一个清除关联流中从光标当前位置到末尾内容的操作添加到内部待处理操作列表中。除非在构造函数中传递了 autoCommit: true
,否则需要调用 rl.commit()
来查看此方法的效果。
rl.commit()
#
- 返回值: <Promise>
rl.commit()
方法将所有待处理操作发送到关联的 stream
并清除内部待处理操作列表。
rl.cursorTo(x[, y])
#
rl.cursorTo()
方法将一个将光标移动到关联 stream
中指定位置的操作添加到内部待处理操作列表中。除非在构造函数中传递了 autoCommit: true
,否则需要调用 rl.commit()
来查看此方法的效果。
rl.moveCursor(dx, dy)
#
rl.moveCursor()
方法将一个将光标相对于其在关联 stream
中的当前位置移动的操作添加到内部待处理操作列表中。除非在构造函数中传递了 autoCommit: true
,否则需要调用 rl.commit()
来查看此方法的效果。
rl.rollback()
#
- 返回值:this
rl.rollback
方法清除内部待处理操作列表,但不将其发送到关联的 stream
。
readlinePromises.createInterface(options)
#
options
<Object>input
<stream.Readable> 要监听的 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
<整数> 一个 Tab 键等于的空格数(最小值为 1)。默认值:8
。
- 返回值:<readlinePromises.Interface>
readlinePromises.createInterface()
方法创建一个新的 readlinePromises.Interface
实例。
const readlinePromises = require('node:readline/promises');
const rl = readlinePromises.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'
事件(当列发生变化时),则 output
流将获得最佳兼容性(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
可读 流和一个 output
可写 流相关联。output
流用于打印用户输入的提示,这些提示到达 input
流并从 input
流读取。
rl.question(query[, options], callback)
#
query
<string> 要写入output
的语句或查询,在提示之前添加。options
<Object>signal
<AbortSignal> 可选地允许使用AbortController
取消question()
。
callback
<Function> 一个回调函数,在用户对query
的输入响应时被调用。
rl.question()
方法通过将 query
写入 output
来显示它,等待用户在 input
上提供输入,然后调用 callback
函数,将提供的输入作为第一个参数传递。
调用时,rl.question()
将恢复 input
流,如果它已被暂停。
如果 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()
方法清除给定 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 数据的可写流。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
<整数> 一个 Tab 键等于的空格数(最小值为 1)。默认值:8
。signal
<AbortSignal> 允许使用 AbortSignal 关闭界面。中止信号将在内部调用界面的close
。
- 返回值:<readline.Interface>
readline.createInterface()
方法创建一个新的 readline.Interface
实例。
const readline = require('node:readline');
const rl = readline.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'
事件(当列发生变化时),则 output
流将获得最佳兼容性(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,则它必须处于原始模式。
这将由任何 readline 实例在其 input
上自动调用,如果 input
是一个终端。关闭 readline
实例不会阻止 input
发出 'keypress'
事件。
readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY)
process.stdin.setRawMode(true);
示例:小型 CLI#
以下示例说明了使用 readline.Interface
类来实现一个小型的命令行界面。
const readline = require('node:readline');
const rl = readline.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
循环。
const fs = require('node:fs');
const readline = require('node:readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.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'
事件。
const fs = require('node:fs');
const readline = require('node:readline');
const rl = readline.createInterface({
input: fs.createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});
目前,for await...of
循环可能有点慢。如果 async
/ await
流和速度都很重要,可以采用混合方法。
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 上无效 |