【问题标题】:node.js fs.exists() will be deprecated, what to use instead?node.js fs.exists() 将被弃用,改用什么?
【发布时间】:2015-10-26 06:25:05
【问题描述】:

根据documentation node.js fs.exists() 将被弃用。 他们的推理:

fs.exists() 是不合时宜的,仅出于历史原因而存在。几乎不应该有理由在您自己的代码中使用它。

特别是,在打开文件之前检查文件是否存在是一种反模式,这会使您容易受到竞争条件的影响:另一个进程可能会在调用 fs.exists() 和 fs.open() 之间删除文件。只需打开文件并在错误不存在时处理它。

fs.exists() 将被弃用。

我目前在移动文件之前使用它,因为 fs.rename() 似乎悄悄地覆盖了目标文件夹中的同名文件。

我的问题是;我应该使用什么来防止 fs.rename() 覆盖目标文件夹中的文件? 我想有一种我不知道的方法。否则我看不到 fs.exists() 被弃用的理由。

按照建议使用 fs.open() 似乎有点矫枉过正,因为我不想打开文件。


编辑,根据@jfriend00 的要求,了解我在做什么的更多信息。

我正在制作一个Electron 应用程序,用户可以在其中将文件分类到不同的目录中。它不是服务器软件,它旨在在每天的用户机器上运行,处理他们的文档。这是目前移动文件的代码:

function moveFile(destIndex){
    var from = queue[currentQueueIndex].path;
    var to = destinations[destIndex].path + path.sep + path.basename(from);
    console.log("[i] Move file (from/to): ");
    console.log(from);
    console.log(to);

    //Check if file exists, if yes: give them the choice to cancel.
    fs.stat(to, function (err, stats) {
        if (err){
            move(from, to);
        } else {
            var confirmed = confirm("File already exists, will overwrite.");
            if (confirmed) {
                move(from, to);
            }
        }
    });
    next(); //Show the next file to the user
}

function move(from, to){
    fs.rename(from, to, function (err) {
        if (err) throw err;
        console.log('[i] Move successful');
        queue[currentQueueIndex].path = to;
        queue[currentQueueIndex].moved = true;
    });
}

在第一个注释之后,以 fs.stat 开头的部分,我检查我将要使用 fs.rename 创建的文件是否已经存在。我想这取决于竞争条件,但我找不到 fs.rename 以任何方式处理重复项。
由于此应用程序旨在用于“家庭计算”,因此我认为文件在统计检查和重命名之间消失的情况不太可能发生。但是,我可以避免的潜在问题越多越好。

【问题讨论】:

  • 你到底想用fs.exists()做什么?我们需要更多关于您的代码序列的详细信息,然后才能提出一些不受竞争条件影响的建议?关键是,任何仅检查存在性然后根据该知识执行操作的替代品都会受到竞争条件的影响,并且可能有更好的编码方式。
  • @jfriend00 - 我已经在主要问题中添加了我正在做的事情以及它的代码。
  • 如果最终用户提示在某种程度为单用户的计算机上,所产生的竞争条件可能并不重要。真正的答案是 fs.rename() 的一个版本,它不会覆盖目标,所以你可以这样调用它,只有当它因为目标存在而无法进行重写时,你会提示并将参数更改为 @987654326 @ 允许覆盖。如果没有事先提示,这将永远不会覆盖。但是,我同意 - 在这种类型的用例中可能不需要。

标签: node.js


【解决方案1】:

使用 fs.existsSync()。

fs.existsSync() 尚未被弃用。

https://nodejs.org/api/fs.html#fs_fs_existssync_path

fs.existsSync(path)

添加于:v0.1.21 路径 | fs.exists() 的同步版本。如果文件存在则返回 true,否则返回 false。

请注意,fs.exists() 已弃用,但 fs.existsSync() 不是。 (fs.exists() 的回调 >parameter 接受与其他 >Node.js 回调不一致的参数。fs.existsSync() 不使用回调。)

【讨论】:

  • 弃用该函数而不是仅仅更改函数接口以与其他 Node.js 回调保持一致似乎很奇怪。
  • 更改函数签名可能会破坏现有代码
【解决方案2】:

io.js docs 提到使用fs.stat()fs.access() 代替fs.exists()

【讨论】:

  • fs.stat() 看起来很有希望,但是当我尝试使用它时 var stat = fs.statSync(file); 我在不存在的文件上收到 ENOENT 错误。我该如何处理?
  • 我搞定了。我将重命名函数放在 stat 函数中,与 4th example here 相反,这允许我使用 stat 而不是 statSync。虽然if(error) doSomething(); 感觉有点怪。
  • @Blargmode - 听起来你正在做的事情仍然受制于竞争条件。
  • @jfriend00 从技术上讲是这样,但 RENAME_NOREPLACE 标志仅添加在 beginning of last year 中,并且不适用于所有文件系统类型,并且是特定于 Linux 的。此外,node/io.js 没有为 renameat2() 提供绑定,这是您将该标志传递给的系统调用。
  • 我已经问过 OP 他们到底在做什么,因为我认为我们可以为他们提供更好的建议来避免竞争条件,而不仅仅是使用同样容易受到相同攻击的 fs.exists() 的替代品比赛条件。在这种情况下,我认为如果 OP 将分享更多关于他们的代码是什么样子以及他们到底想要做什么的信息,那么我认为有一个比仅仅为他们提供这个解决方法更好的答案。
【解决方案3】:

这是一个使用 fs.access 的示例(在旧的 Node 版本中,使用 fs.stat 而不是 fs.access),但也可以正确处理错误:

async function fileExists(filename) {
    try {
        await fs.promises.access(filename);
        return true;
    } catch (err) {
        if (err.code === 'ENOENT') {
            return false;
        } else {
            throw err;
        }
    }
}

【讨论】:

    【解决方案4】:

    这里是使用fs.stat的示例:-

    fs.stat('mycustomfile.csv', function (err, stats) {
       console.log(stats);//here we got all information of file in stats variable
       if (err) {
           return console.error(err);
       }
         fs.unlink('mycustomfile.csv',function(err){
            if(err) return console.log(err);
            console.log('file deleted successfully');
       });  
    });
    

    【讨论】:

    • 也许我想处理文件不存在的情况,而不是发生其他错误。我该如何处理?
    【解决方案5】:
    const exists = !!(await fs.promises.stat(filename).catch(() => null))
    

    【讨论】:

      猜你喜欢
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-08
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      相关资源
      最近更新 更多