在Node.js中删除文件

16
我正在Windows环境下使用Node。 当我使用fs.unlinkSync(fileName)时,它似乎起作用了。 执行unlinkSync语句后,如果我执行fs.existsSync(filename),它返回false,表示文件不存在,但当我去到物理驱动器上时,我仍然可以看到该文件。
此时,如果我尝试手动删除该文件,它会抛出“访问被拒绝”的错误。 但是,只有在停止执行node脚本文件时,文件系统才会自动将该文件从文件系统中删除。
这是预期的行为吗?

1
我非常确定这是因为文件由于某种原因被Windows锁定了。这种行为是DeleteFile SDK的一部分,所以Node.js无法做太多事情。 - mekwall
2
你需要展示更多的代码。如果文件没有被正确地关闭,unlink操作将在进程退出后排队执行。 - WiredPrairie
2个回答

25
如果文件在您的NodeJS代码中被打开但未关闭,则会遇到您所经历的行为。在Windows上,它的行为是符合预期的。
以这段代码为例:
var fs = require('fs');

var filename = "D:\\temp\\temp.zip";
var tempFile = fs.openSync(filename, 'r');
// try commenting out the following line to see the different behavior
fs.closeSync(tempFile);

fs.unlinkSync(filename);

如果代码使用openSync然后在文件上调用closeSync,当调用unlinkSync时,文件将立即被删除。但是,如果您删除closeSync调用,您会发现文件仅在NodeJS进程干净地退出时才被删除。这只是导致此问题出现的一种方式的例子。

如果您正在使用处理文件等内容的第三方库,则可能代码没有正确关闭文件句柄/描述符,您也会遇到此问题(出于相同的原因)。

注意:如果您在Linux操作系统上测试此代码,该文件将立即被删除。这是操作系统之间行为差异和文件删除方式的区别。

详细信息

在Windows上,当NodeJS删除文件时,实际上并没有直接调用API来删除文件。相反,它使用了一个名为ZwSetInformation的低级函数(参考文献)。使用该函数,它将为指定的文件(句柄)设置一个称为DeleteFile的字段为TRUE。这样,当该文件的所有文件句柄都关闭时,它将自动删除。在NodeJS中,文件以FILE_SHARE_DELETE访问模式打开,以便可以通过使用其他函数正确删除它们。


谢谢...缺少closeSync函数调用。非常感谢。 - user1961100
这对我仍然没有用。即使在fs.closeSync / fs.unlinkSync之后,我仍然会得到隐藏的锁定文件。这些文件仍然存在于Windows资源管理器中,但是任何尝试删除它们都需要本地管理员权限,而这个管理员只有我自己。 - Robbie Smith

0

我在使用这个创建新文件时遇到了类似的问题

lib.create = function (directory, fileName, data) {
  return fs.promises.open(`${lib.baseDir}${directory}/${fileName}.json`, "wx")
    .then(fileHandle => {
      // Convert data to string
      const stringData = JSON.stringify(data);

      return fileHandle.writeFile(stringData)
        .then(() => Promise.resolve(`File '${fileName}.json' saved successfully`))
        .catch(() => Promise.reject("Error writing to new file"));
    })
    .catch(() => Promise.reject("Could not create new file, it may already exist"));
}; 

并且这个用于删除文件

lib.delete = function (directory, fileName) {
  return fs.promises.unlink(`${lib.baseDir}${directory}/${fileName}.json`)
    .then(() => Promise.resolve(`File '${fileName}.json' deleted successfully`))
    .catch(() => Promise.reject(`Error deleting a ${fileName}.json`))
};

在关闭Node应用程序后,我的文件被删除了。原因是

fileHandle.writeFile

不会自动关闭文件,需要做的是:

fileHandle.writeFile

返回一个 Promise,这样我们就可以添加另一个 then 并在那里关闭文件。

return fileHandle.writeFile(stringData)
   .then(() => fileHandle.close())
      .then(() => Promise.resolve(`File '${fileName}.json' saved successfully`))
   .catch(() => Promise.reject("Error writing to new file"));

现在我的删除功能很好用!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接