仅当 Node.js 中不存在文件时才创建文件

新手上路,请多包涵

我们有一个要写入文件的缓冲区。如果文件已经存在,我们需要增加一个索引,然后再试一次。有没有办法只在文件不存在的情况下创建文件,或者我应该只统计文件,直到出现错误以找到一个不存在的文件?

例如,我有文件 a_1.jpga_2.jpg 。我想我的方法尝试创建 a_1.jpga_2.jpg ,失败,最后成功创建 a_3.jpg

理想的方法如下所示:

 fs.writeFile(path, data, { overwrite: false }, function (err) {
  if (err) throw err;
  console.log('It\'s saved!');
});

或像这样:

 fs.createWriteStream(path, { overwrite: false });

节点的 fs 库中是否存在类似的东西?

_编辑_:我的问题不是是否有一个单独的函数来检查是否存在。就是这样:如果文件不存在,有没有办法在单个文件系统调用中创建文件?

原文由 configurator 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
1 个回答

正如您的直觉正确猜到的那样,带有一对 exists / writeFile 调用的天真解决方案是错误的。异步代码以不可预测的方式运行。在给定的情况下是

  • 有文件 a.txt 吗? - 不。
  • (文件 a.txt 由另一个程序创建)
  • 写信给 a.txt 如果可能的话。 - 好的。

但是,是的,我们可以在一个电话中做到这一点。我们正在使用文件系统,因此最好阅读 fs 上的开发人员手册。嘿, 这是 一个有趣的部分。

‘w’ - 打开文件进行写入。该文件被创建(如果它不存在)或被截断(如果它存在)。

‘wx’ - 类似于 ‘w’ 但如果路径存在则失败。

所以我们所要做的就是将 wx 添加到 fs.open 调用中。但是,嘿,我们不喜欢 fopen 像 IO。让我们继续阅读 fs.writeFile 多一点。

fs.readFile(文件名[, 选项], 回调)#

文件名 字符串

选项对象

编码字符串 |空默认 = 空

标志字符串默认值 = ‘r’

回调函数

那个 options.flag 看起来很有希望。所以我们尝试

fs.writeFile(path, data, { flag: 'wx' }, function (err) {
    if (err) throw err;
    console.log("It's saved!");
});

它非常适合单次写入。我想如果你试图用它来解决你的任务,这段代码会以一些更奇怪的方式失败。你有一个原子“检查 a_#.jpg 存在,如果它是空的就写在那里”操作,但所有其他 fs 状态未锁定,并且 a_1.jpg 可能会在您已经检查 a_5.jpg 时自发消失。大多数 * 文件系统都不是 ACID 数据库,而且您至少能够执行一些原子操作这一事实是不可思议的。 wx 代码很可能无法在某些平台上运行。所以为了你的理智, _最后使用数据库_。

有关苦难的更多信息

想象一下我们正在编写类似 memoize-fs 的东西,它缓存函数调用的结果到文件系统以节省我们一些网络/cpu 时间。如果文件存在,我们是否可以打开文件进行读取,如果文件不存在,则可以进行写入,所有这些都在一次调用中完成?让我们有趣地看看这些旗帜。经过一段时间的脑力练习后,我们可以看到 a+ 做了我们想要的:如果文件不存在,它会创建一个并打开它进行读写,如果文件存在,它会这样做不清除文件(就像 w+ 那样)。但是现在我们不能在 (smth)Filecreate(Smth)Stream 函数中使用它。这似乎是一个缺失的功能。

所以请随意将它作为功能请求(甚至是错误)提交给 Node.js github,因为缺少原子异步文件系统 API 是 Node.js 的一个缺点。尽管 不要指望 很快会发生变化。

编辑。我想链接到 LinusDan Luu 的文章,内容是关于为什么您不想对您的 fs 调用做任何聪明的事情,因为该声明基本上没有任何依据。

原文由 polkovnikov.ph 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏