Node js 在复制之前检查文件是否打开

Jam*_*ris 2 javascript fs node.js

在将文件复制到另一个位置之前,我需要检查文件是否已打开。下面的代码告诉您打开文件时是否显示错误代码 = EBUSY。但如果文件未打开,它将删除文件的内容。有没有更好的方法来获取这些信息。

    fs.open('my-file.dwg','w', function(err,data) {

    });
Run Code Online (Sandbox Code Playgroud)

chr*_*ris 5

警告:我发布此内容是因为接受的答案不起作用。不过,我不是 Windows 文件锁定方面的专家,但这就是我能够拼凑出来的:

在 Windows 上,似乎有 3 种类型的锁会导致EBUSYNode.js 中的错误。

  1. 使用“独占锁”锁定的文件
  2. 当前正在运行的操作系统锁定的可执行文件
    • 例如当你运行setup.exe
  3. 系统保护的文件
    • 例如C:\hiberfil.sys

选项A:

Node fs 构建于libuv之上,它允许传递高级选项来请求独占锁。这似乎是最安全的技术,因为没有机会更改/损坏文件。

使用UV_FS_O_RDONLYUV_FS_O_EXLOCK打开文件

EBUSY 返回 1、2 和 3。

try {
   const fileHandle = await fs.promises.open(filePath, fs.constants.O_RDONLY | 0x10000000);

  fileHandle.close();
} catch (error) {
  if (error.code === 'EBUSY'){
    console.log('file is busy');
  } else {
    throw error;
  }
}

Run Code Online (Sandbox Code Playgroud)

注意:这需要 libuv >= 1.17.0,NodeJS >= 满足这一点8.10.0

选项B:

在锁定的文件上执行fs.rename()也可靠地失败,不需要任何操作系统特定的标志,但更危险,因为您可能会引入竞争条件错误,因为文件实际上是临时移动的。

EBUSY 返回 1、2 和 3。

try {
  await fs.promises.rename(filePath, filePathNew);

  await fs.promises.rename(filePathNew, filePath);
} catch (error) {
  if (error.code === 'EBUSY'){
    console.log('file is busy');
  } else {
    throw error;
  }
}
Run Code Online (Sandbox Code Playgroud)

选项C(不使用):

执行fs.open(..., 'r+'). 这对于具有排他锁 1 的文件不起作用,不会返回错误。

EBUSY 返回 2 和 3。

try {
  await fs.promises.open(filePath, 'r+');
} catch (error) {
  if (error.code === 'EBUSY'){
    console.log('file is busy');
  } else {
    throw error;
  }
}
Run Code Online (Sandbox Code Playgroud)