Node js проверяет, открыт ли файл перед копированием

Мне нужно проверить, открыт ли файл, прежде чем копировать его в другое место. В приведенном ниже коде указано, открыт ли он с кодом ошибки = EBUSY. Но если файл не открыт, он стирает содержимое файла. Есть ли лучший способ получить эту информацию.

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

    });

person James Morris    schedule 18.02.2015    source источник
comment
Один момент — почему не используется модуль fs-extra для node.js — npmjs.com/package/ фс-экстра?   -  person Piyas De    schedule 18.02.2015
comment
также вы можете получить помощь от - stackoverflow.com/questions/11293857/   -  person Piyas De    schedule 18.02.2015
comment
@PiyasDe Я не знал о fs-extra, но я проверю. Спасибо.   -  person James Morris    schedule 18.02.2015
comment
См.: stackoverflow.com/a/44760825/2138743.   -  person Joran Greef    schedule 26.06.2017


Ответы (2)


Мне кажется, что вы можете использовать r+:

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

});

Из документов модуля fs:

'r+' - Открыть файл для чтения и записи. Исключение возникает, если файл не существует.

Если файл уже открыт кем-то другим, он не должен давать вам права на чтение и запись и должен возвращать ошибку. Это не создаст файл, если он не существует.

Параметр r+ не усекает и не создает файл, как это делает параметр w+.

person jfriend00    schedule 18.02.2015

Предостережение: я публикую это, так как принятый ответ не работает. Однако я не эксперт по блокировке файлов Windows, но вот что мне удалось собрать вместе:

В Windows существует 3 типа блокировки, которые вызывают ошибку EBUSY в Node.

  1. Files locked with an 'exclusive lock'
  2. Executable files locked by the OS which are currently running
    • e.g. when you run a setup.exe
  3. System protected files
    • e.g. C:\hiberfil.sys

Вариант А:

Node fs построен на основе libuv, которая позволяет передавать дополнительные параметры для запроса эксклюзивной блокировки. Это кажется самым безопасным методом, так как нет шансов изменить/испортить файл.

Откройте файл с помощью UV_FS_O_RDONLY и UV_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;
  }
}

Примечание: для этого требуется libuv ›= 1.17.0, что удовлетворяет NodeJS ›= 8.10.0

Вариант Б:

Выполнение 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;
  }
}

Вариант С (не использовать):

Выполните 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;
  }
}
person chris    schedule 16.10.2020