我一直在摆弄Node.js,发现了一个小问题。我有一个脚本驻留在一个名为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创建目录结构,如果它不退出写入文件?


当前回答

下面是一个完整的解决方案,在一个函数中创建包含所有所需子文件夹的文件夹,然后写入文件。

这是一个示例,假设您正在创建一个备份文件,并且希望在函数中传递备份文件夹名称(因此变量名称)


  createFile(backupFolderName, fileName, fileContent) {
    const csvFileName = `${fileName}.csv`;

    const completeFilePath = join(process.cwd(), 'backups', backupFolderName);

    fs.mkdirSync(completeFilePath, { recursive: true });

    fs.writeFileSync(join(completeFilePath, csvFileName), fileContent, function (err) {
      if (err) throw err;
      console.log(csvFileName + ' file saved');
    })
  }

其他回答

如果你不想使用任何额外的包,你可以在创建文件之前调用下面的函数:

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);
}

由于我还不能评论,我发布了一个基于@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);
}

下面是一个完整的解决方案,在一个函数中创建包含所有所需子文件夹的文件夹,然后写入文件。

这是一个示例,假设您正在创建一个备份文件,并且希望在函数中传递备份文件夹名称(因此变量名称)


  createFile(backupFolderName, fileName, fileContent) {
    const csvFileName = `${fileName}.csv`;

    const completeFilePath = join(process.cwd(), 'backups', backupFolderName);

    fs.mkdirSync(completeFilePath, { recursive: true });

    fs.writeFileSync(join(completeFilePath, csvFileName), fileContent, function (err) {
      if (err) throw err;
      console.log(csvFileName + ' file saved');
    })
  }

我只是发布了这个模块,因为我需要这个功能。

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

它的工作原理类似于Node.js fs方法的包装器。所以你可以像处理fs一样使用它。writeFile和fs。writeFileSync(异步和同步写入)

与上面相同的答案,但异步等待和准备使用!

const fs = require('fs/promises');
const path = require('path');

async function isExists(path) {
  try {
    await fs.access(path);
    return true;
  } catch {
    return false;
  }
};

async function writeFile(filePath, data) {
  try {
    const dirname = path.dirname(filePath);
    const exist = await isExists(dirname);
    if (!exist) {
      await fs.mkdir(dirname, {recursive: true});
    }
    
    await fs.writeFile(filePath, data, 'utf8');
  } catch (err) {
    throw new Error(err);
  }
}

例子:

(async () {
  const data = 'Hello, World!';
  await writeFile('dist/posts/hello-world.html', data);
})();