Using fs.stat and fs.writeFile



我需要在执行fs.writeFile之前检查文件是否存在,所以如果文件已经存在,fs.writeFile不替换文件。但文档说:

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

如果我直接调用fs.writeFile,该函数将替换文件(如果该文件已经存在),并且error变量将null

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

谢谢。

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

使用wx标志(在此处记录):

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.open/fs.writeFile/fs.readFile之前使用fs.stat的原因是因为固有的竞争条件:在调用fs.stat和(比如)fs.writeFile之间,有一个很小的时间窗口可以创建一个文件,即使调用fs.stat时它还不存在。因此,fs.writeFile仍有可能覆盖现有文件。

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

罗伯特有正确的答案(只需在适当的标志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()报告文件不存在的情况,但是在那一刻和您实际调用fs.writeFile()的时间之间,其他一些进程或线程或计算机写入该文件,现在您刚刚覆盖了您不想做的现有文件。 因此,这在某些情况下根本不可靠,因此不建议使用。

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

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


竞争条件是有限制的,在某些情况下,你的系统实际上不会受到它的约束(只有一个节点.js进程可以写入该文件),但无论如何,始终以安全的方式编码是更安全的,事实上,安全的方式也是更少的代码。

最新更新