NodeJs:fs.stat()或fs.access()检查文件夹是否存在?

时间:2019-02-04 10:54:41

标签: node.js fs

我目前正在尝试在将文件保存到本地文件夹之前,找出一种检查本地文件夹是否存在的“正确”方法,这对nodejs文档有些困惑。

fs.exists()已过时,您应该使用fs.stat()或fs.access()。到目前为止一切顺利。

fs.stat():

  

不建议在调用fs.open(),fs.readFile()或fs.writeFile()之前使用fs.stat()检查文件是否存在。相反,用户代码应直接打开/读取/写入文件,并处理文件不可用时引发的错误。

这表明,我应该尝试编写,捕获错误,创建文件夹,然后重试。即使我正在移动/重命名文件,我也可以,所以我不直接使用提到的三个功能之一。

然后,医生说:

  

要检查文件是否存在而不随后对其进行操作,建议使用fs.access()。

由于我并没有真正修改文件,而是“仅”修改了文件的内容,因此有人可能会认为这是修改的方法。

但是再说一次,fs.access()文档详细介绍了为什么这也是个坏主意:

  

不建议在调用fs.open(),fs.readFile()或fs.writeFile()之前使用fs.access()检查文件的可访问性。这样做会引入竞争条件,因为其他进程可能会在两次调用之间更改文件的状态。相反,用户代码应直接打开/读取/写入文件,并处理无法访问文件时引发的错误。

Yadda yadda yadda,已经存在一些相关问题(herehere),但是是否有不超过两年的“最佳实践”的官方信息? >

4 个答案:

答案 0 :(得分:6)

我猜该文档建议在以后没有任何操作时使用fs.access检查文件是否存在,这是因为它是较低级别的简单API,仅用于检查文件访问元数据(包括是否文件是否存在)。一个简单的API可能在性能方面也要好一点,因为它可能只是直接映射到底层本机代码。(注意:我没有做任何基准测试,请以我的观点为依据盐)。

fs.stat相比,

fs.access提供了更高级别的抽象。它返回文件访问以外的信息。

import {promises as fs} from "fs";
import * as oldfs from "fs";

(async function() {
    // fs.stat has higher level abstraction
    const stat = await fs.stat(__dirname);
    console.log(stat.isDirectory());
    console.log(stat.isFile());
    console.log(stat.ctime);
    console.log(stat.size);

    try {
        // fs.access is low level API, it throws error when it doesn't match any of the flags
        // is dir exists? writable? readable?
        await fs.access(__dirname, oldfs.constants.F_OK | oldfs.constants.W_OK | oldfs.constants.R_OK);
    } catch (error) {
        console.log(`${__dirname} is not exists / writable / readable`);
    }
})();

答案 1 :(得分:0)

我认为该文档是不言自明的。

如果您只想检查文件是否存在-不尝试随后打开/读取/写入文件,则应使用access:

// Check if the file exists in the current directory, and if it is writable.
fs.access(file, fs.constants.F_OK | fs.constants.W_OK, (err) => {
  if (err) {
    console.error(
      `${file} ${err.code === 'ENOENT' ? 'does not exist' : 'is read-only'}`);
  } else {
    console.log(`${file} exists, and it is writable`);
  }
});

如果要打开/读取/写入文件,则不应调用access来检查其是否存在,而应直接执行操作并自己处理错误:

//write (NOT RECOMMENDED)

fs.access('myfile', (err) => {
  if (!err) {
    console.error('myfile already exists');
    return;
  }

  fs.open('myfile', 'wx', (err, fd) => {
    if (err) throw err;
    writeMyData(fd);
  });
});

//write (RECOMMENDED)

fs.open('myfile', 'wx', (err, fd) => {
  if (err) {
    if (err.code === 'EEXIST') {
      console.error('myfile already exists');
      return;
    }

    throw err;
  }

  writeMyData(fd);
});

这些示例来自您链接的文档。

如果在启动时进行简单检查,还可以使用不推荐使用的existsSync()-避免在循环中多次使用它,因为这会阻塞nodejs事件循环。 / p>

答案 2 :(得分:0)

尽管我不认为节点支持它,但正确的方法是打开目录以获取dirfd。那应该只使用open,然后才能在dirfd或fd上调用faccess或fstat。 然后,如果打开目录成功,则将dirfd与openat一起使用以打开文件。

我写了一个使用fs.createReadStream的http服务器,如果路径不是文件,则处理该错误。它还使用了暂停和恢复功能,以便能够在流开始传递到响应之前在打开的文件上使用fstat。

答案 3 :(得分:0)

您可以轻松地通过a = np.random.randint(1,101,15) array([79, 86, 88, 87, 78, 43, 57]) 进行同步。

但是,如果您要异步进行操作,只需执行以下操作:

existsSync()

或者将其放在这样的try-catch中...

await fs.promises.access("path");