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

Node js check if a file is open before copy

本文关键字:文件 是否 检查 js 复制 Node      更新时间:2023-12-31

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

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

在我看来,您可以使用r+:

fs.open('my-file.dwg','r+', function(err,data) {
});

来自fs模块文档:

"r+"-打开文件进行读取和写入。如果文件不存在。

如果文件已经被其他人打开,那么它不应该授予您读写权限,并且应该返回一个错误。如果不存在,则不会创建该文件。

r+选项不会像w+选项那样截断或创建文件。

注意:我发布这个是因为接受的答案不起作用。然而,我不是Windows文件锁定专家,但这是我能够拼凑起来的:

在Windows上,似乎有三种类型的锁会导致Node中的EBUSY

  1. 使用"独占锁"锁定的文件
    • 例如,当您在MS Word中打开文档时
    • 在Windows Fileapi.h中,这些文件是用CreateFileW(dwShareMode:0)和LockFileEx(dwFlags)创建的
  2. 当前正在运行的操作系统锁定的可执行文件
    • 例如,当您运行setup.exe
  3. 受系统保护的文件
    • 例如C:'hiberfil.sys

选项A:

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

使用UV_FS_O_RDONLY和UV_FS_O_2 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;
  }
}

注意:这需要libuv>=NodeJS满足的1.17.0>=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;
  }
}

选项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;
  }
}