如何在 JS 中快速读取文件

本文翻译自 How to read files quickly in JavaScript,作者:Daniel Lemire, 略有删改。

假设你需要在服务器上使用JavaScript读取多个文件。在像Node.js这样的运行时环境中,JavaScript有多种读取文件的方式。哪一种是最好的呢?让我们来看看各种方法的测试结果。

使用fs. promise

const fs = require('fs/promises');
const readFile = fs.readFile;
readFile("lipsum.txt", { encoding: 'utf-8' })
  .then((data) => {...})
  .catch((err) => {...})

使用fs.readFile和util.promisify

const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
readFile("lipsum.txt", { encoding: 'utf-8' })  
  .then((data) => {...})
  .catch((err) => {...})

使用fs.readFileSync

const fs = require('fs');
const readFileSync = fs.readFileSync;
var data = readFileSync("lipsum.txt", { encoding: 'utf-8' })

使用await fs.readFileSync

const fs = require('fs');
const readFileSync = fs.readFileSync;
async function f(name, options) {
  return readFileSync(name, options);
}

使用fs.readFile

const fs = require('fs');
const readFile = fs.readFile;
fs.readFile('lipsum.txt', function read(err, data) {...});

测试

我写了一个小型基准测试,用于反复从磁盘读取文件。这是一个简单的循环,每次都会访问相同的文件。我记录了读取文件5万次所需的毫秒数。这个文件相对较小(略超过1千字节)。我使用的是一台拥有数十个Ice Lake Intel核心和大量内存的大型服务器。我使用的Node.js版本是20.1,Bun版本是1.0.14

我多次运行了基准测试,并且在所有情况下都记录了最好的结果。你的结果可能会有所不同。

时间(Node.js)时间(Bun)
fs.promises2400 ms110 ms
fs.readFile和util.promisify1500 ms180 ms
fs.readFileSync140 ms140 ms
await fs.readFileSync220 ms180 ms
fs.readFile760 ms90 ms

至少在我的系统上,在这个测试中使用Node.js时,fs.promises比其他方式都要慢的多。在这个测试中Bun比Node.js快得多。

从某种意义上来说,fs.promises 的结果比看上去更差。我发现 readFileSync 使用了 300 毫秒的 CPU 时间,而 fs.promises 却使用了 7 秒的 CPU 时间。这是因为在进行基准测试时,fs.promises 在多个核心上触发了工作。

即使将文件大小增加到32kB,结论也并没有改变。如果你使用更大的文件,许多Node.js案例会因为“堆内存分配失败”而失败。但Bun即使处理大文件也能继续运行。测试结果并没有改变关于Bun的结论:在我的测试中,fs.readFile始终更快,即使对于大文件也是如此。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果你要读取 JavaScript 文件的特定内容,可以使用 Python 的正则表达式或者解析库来解析 JavaScript 文件。下面提供两种方法: 方法一:使用正则表达式 使用正则表达式可以快速地从 JavaScript 文件提取特定内容。例如,如果你要从 JavaScript 文件提取以`var data = `开头的变量声明,可以使用以下代码: ```python import re with open('example.js', 'r') as f: content = f.read() pattern = r'var data = (.+?);' result = re.search(pattern, content) if result: data = result.group(1) print(data) else: print('No match found.') ``` 在上面的代码,首先使用 `with open()` 函数打开 JavaScript 文件并读取其的内容。然后,使用正则表达式 `r'var data = (.+?);'` 匹配以`var data = `开头的变量声明,并使用 `re.search()` 函数在文件查找这个模式。最后,使用 `result.group(1)` 从匹配结果提取出变量声明的内容。 方法二:使用 JavaScript 解析库 除了使用正则表达式外,你还可以使用 JavaScript 解析库来解析 JavaScript 文件。例如,可以使用 `slimit` 库来解析 JavaScript 文件并提取其的内容: ```python from slimit import ast from slimit.parser import Parser from slimit.visitors import nodevisitor with open('example.js', 'r') as f: content = f.read() # 解析 JavaScript 文件 tree = Parser().parse(content) # 遍历语法树并查找特定节点 for node in nodevisitor.visit(tree): if isinstance(node, ast.VarDecl) and node.identifier.value == 'data': data = node.initializer.to_ecma() print(data) ``` 在上面的代码,首先使用 `with open()` 函数打开 JavaScript 文件并读取其的内容。然后,使用 `slimit.parser.Parser` 类将 JavaScript 文件解析为语法树。最后,使用 `slimit.visitors.nodevisitor` 模块的 `visit()` 函数遍历语法树并查找特定节点(在这个例子,查找变量声明名为 `data` 的变量),然后使用 `to_ecma()` 方法将节点转换为 ECMAScript(JavaScript)代码。 需要注意的是,如果要使用 `slimit` 库需要先使用 `pip install slimit` 安装。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南城FE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值