Подтвердить что ты не робот

Создать каталог при записи в файл Node.js

Я возился с Node.js и обнаружил небольшую проблему. У меня есть скрипт, который находится в каталоге с именем data. Я хочу, чтобы скрипт записывал некоторые данные в файл в подкаталоге внутри подкаталога data. Однако я получаю следующую ошибку:

{ [Error: ENOENT, open 'D:\data\tmp\test.txt'] errno: 34, code: 'ENOENT', path: 'D:\\data\\tmp\\test.txt' }

Код выглядит следующим образом:

var fs = require('fs');
fs.writeFile("tmp/test.txt", "Hey there!", function(err) {
    if(err) {
        console.log(err);
    } else {
        console.log("The file was saved!");
    }
}); 

Кто-нибудь может мне помочь выяснить, как заставить Node.js создавать структуру каталогов, если она не выходит для записи в файл?

4b9b3361

Ответ 1

Узел> 10.12.0

fs.mkdir теперь принимает параметр { recursive: true } например:

// Creates /tmp/a/apple, regardless of whether '/tmp' and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

или с обещанием:

fs.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);

Узел <= 10.11.0

Вы можете решить эту проблему с помощью пакета, такого как mkdirp или fs-extra. Если вы не хотите устанавливать пакет, см. Ответ Tiago Peres França ниже.

Ответ 2

Если вы не хотите использовать какой-либо дополнительный пакет, вы можете вызвать следующую функцию перед созданием файла:

var path = require('path'),
    fs = require('fs');

function ensureDirectoryExistence(filePath) {
  var dirname = path.dirname(filePath);
  if (fs.existsSync(dirname)) {
    return true;
  }
  ensureDirectoryExistence(dirname);
  fs.mkdirSync(dirname);
}

Ответ 3

Бесстыдное предупреждение о подключении!

Вам нужно будет проверить каждый каталог в структуре пути, который вы хотите, и создать его вручную, если он не существует. Все инструменты для этого уже существуют в модуле Node fs, но вы можете сделать все это просто с моим модулем mkpath: https://github.com/jrajav/mkpath

Ответ 4

С node-fs-extra вы можете сделать это легко.

Установить его

npm install --save fs-extra

Затем используйте метод outputFile. В его документации сказано:

Почти так же, как writeFile (то есть перезаписывает), за исключением того, что если родительский каталог не существует, он создается.

Вы можете использовать его тремя способами:

Стиль обратного вызова

const fse = require('fs-extra');

fse.outputFile('tmp/test.txt', 'Hey there!', err => {
  if(err) {
    console.log(err);
  } else {
    console.log('The file was saved!');
  }
})

Использование обещаний

Если вы используете обещания, и я надеюсь, что это код:

fse.outputFile('tmp/test.txt', 'Hey there!')
   .then(() => {
       console.log('The file was saved!');
   })
   .catch(err => {
       console.error(err)
   });

Синхронизировать версию

Если вы хотите синхронизировать версию, просто используйте этот код:

fse.outputFileSync('tmp/test.txt', 'Hey there!')

Для полной справки, проверьте документацию outputFile и все поддерживаемые методы node-fs-extra.

Ответ 5

Так как я еще не могу комментировать, я публикую расширенный ответ на основе фантастического решения @tiago-peres-frança (спасибо!). Его код не создает каталог в случае, когда в пути отсутствует только последний каталог, например. вход "C:/test/abc" и "C:/test" уже существует. Вот фрагмент, который работает:

function mkdirp(filepath) {
    var dirname = path.dirname(filepath);

    if (!fs.existsSync(dirname)) {
        mkdirp(dirname);
    }

    fs.mkdirSync(filepath);
}

Ответ 6

Мой совет: старайтесь не полагаться на зависимости, когда вы можете легко сделать это с несколькими строками кодов

Вот что вы пытаетесь достичь в строках 14:

fs.isDir = function(dpath) {
    try {
        return fs.lstatSync(dpath).isDirectory();
    } catch(e) {
        return false;
    }
};
fs.mkdirp = function(dirname) {
    dirname = path.normalize(dirname).split(path.sep);
    dirname.forEach((sdir,index)=>{
        var pathInQuestion = dirname.slice(0,index+1).join(path.sep);
        if((!fs.isDir(pathInQuestion)) && pathInQuestion) fs.mkdirSync(pathInQuestion);
    });
};

Ответ 7

Я только что опубликовал этот модуль, потому что мне нужна эта функциональность.

https://www.npmjs.org/package/filendir

Он работает как обертка вокруг методов Node.js fs. Таким образом, вы можете использовать его точно так же, как с fs.writeFile и fs.writeFileSync (как для асинхронной, так и синхронной записи)