使用fs.stat和fs.writeFile

时间:2017-08-26 15:38:45

标签: node.js fs

我需要在执行fs.writeFile之前检查文件是否存在,因此如果文件已经存在,则fs.writeFile不能替换该文件。但文档说明如下:

  

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

如果我直接致电fs.writeFile,该函数会替换该文件(如果该文件已存在),error变量将为null

如果文件已存在,我想忽略对fs.writeFile的调用。

感谢。

2 个答案:

答案 0 :(得分:1)

  

如果文件已存在,我想忽略对fs.writeFile的调用。

使用wx标记(记录为here):

  

wx - 与'w'类似,但如果路径存在则失败。

fs.writeFile('/path/to/file', data, { flag : 'wx' }, function(err) {
  if (err && err.code === 'EEXIST') {
    console.log('file already exists, not overwriting');
    return;
  }
  ...
})

编辑:不建议在fs.stat之前使用fs.open/fs.writeFile/fs.readFile的原因是由于固有的竞争条件:在fs.stat和({ ()fs.writeFile,有一个小窗口的时间可以创建文件 ,即使在调用fs.stat时它还不存在。因此,fs.writeFile仍有可能覆盖现有文件。

如果使用文件标志,则检查存在是否以原子方式完成。

答案 1 :(得分:1)

罗伯特有正确的答案(只需传递适当的旗帜fs.writeFile(fname, data, { flag : 'wx' }, ...)),但我想我会解释为什么不建议使用fs.stat()后跟fs.writeFile()。当你做这样的事情时:

fs.stat(fname, function(err) {
    if (err) {
       // in the bit of time right here, there is a race condition
       fs.writeFile(fname, data, function(err) {
           // file written
       });
    }
});

有竞争条件。在任何类型的多进程系统或与其他系统共享的任何类型的文件系统中,可能存在fs.stat()报告文件不存在但在该时刻与您实际调用的时间之间的情况{{ 1}},其他一些进程或线程或计算机写入该文件,现在您只是覆盖了一个您不想做的事情的现有文件。因此,在某些情况下这根本不可靠,因此不建议这样做。

你需要的是一个原子操作,既检查它是否存在,如果没有,将为你创建它。这将为您提供一个可靠的系统,以便永远不会意外覆盖该文件。

通过将fs.writeFile()标志传递给wx,只有当文件已经存在并且它将在原子中完成时,才告诉底层操作系统将这些字节写入文件没有多线程/进程/计算机竞争条件的时尚。

竞争条件存在限制,并且在某些情况下您的系统实际上不会受其影响(只有一个node.js进程可以写入该文件),但只是总是编码更安全安全的方式,无论如何,事实上,安全的方式也是更少的代码。