用NodeJS读取文件返回`ENOENT no such file或directory`

时间:2018-02-09 16:55:19

标签: node.js

我试图读取文件,但我总是收到错误Error: ENOENT: no such file or directory, open \'SB01028A.RET\'。文件名是正确的,并且存在,因为我将文件放在我的Home / sentbox目录中。

我在这里做错了什么?

代码:

function downloadFile () {
  return new Promise((resolve, reject) => {
    try {
      const testFolder = `${require('os').homedir()}/sentbox`

      fs.readdir(testFolder, (err, files) => {
        if (err) {
          return reject(err)
        }
        files.forEach(fileRetorno => {
          const retorno = fs.readFileSync(fileRetorno, 'UTF8')
          return resolve(retorno)
        })
      })
    } catch (err) {
      return reject(err)
    }
  })
}

1 个答案:

答案 0 :(得分:0)

您的代码中存在许多错误,例如

  • 当您可以使文件读取异步时,在承诺中使用同步文件读取
  • 在异步上下文中使用try/catch,而不将其包含在async/await函数
  • 您未正确使用fs.readdir()的结果。
  • 试图解决/拒绝可能已经解决或拒绝的承诺
  • 在循环和异步上下文中使用require()

fs.readdir()将返回该目录中的所有条目名称,包括文件和目录,作为数组。在调用fs.readFile()之前,您需要检查条目是文件还是目录,在这种情况下,您需要join()使用readdir()读取目录的路径, testFolder,条目名称。

使用Promises返回时(async/await包装承诺但仍然使用它们),您只能解决一次承诺。因此,多次解析相同的承诺以返回不同的值不起作用,拒绝多次也是如此。相反,您需要在Array或Object中返回值。对于上面代码中的场景,使用Object会更理想,因为您可以将文件内容关联到一个键以供参考,以便以后更好地访问。

我已经使用async/await来清理这段代码,这将为您提供同步开发方法,同时获得promises的功能。您可以在MDN上详细了解async/await。我还使用util.promisify()

宣传所有必需的fs函数的异步版本

以下代码

  1. 阅读testFolder
  2. 中的所有条目
  3. 通过为每个条目调用stat()并检查它是否是文件,将条目数组过滤为仅包含文件。
    • stat()将返回fs.Stat对象,该对象可以通过stat.isFile()告诉我们该条目是否为文件。由于Array#filter()只期望对每个条目进行一次布尔结果,因此stat.isFile()的结果可以直接返回
  4. 使用filesArray#reduce()数组进行迭代,并为每个文件调用readFile(),并在对象上返回内容,并将每个文件名作为内容的关键
  5. const fs = require('fs')
    const {promisify} = require('util')
    const os = require('os')
    const path = require('path')
    const readdir = promisify(fs.readdir)
    const readFile = promisify(fs.readFile)
    const stat = promisify(fs.stat)
    
    const downloadFile = async () => {
      const testFolder = `${os.homedir()}/sentbox`
      // Get all the entries in the directory async
      const entries = await readdir(testFile)
    
      // We only want the file entries returned
      const files = entries.filter(async entry => {
        let stat = await stat(path.join(testFolder, entry))
        return stat.isFile()
      })
    
      return Promise.all(files.reduce(async (filesContents, file) => {
        let filepath = path.join(testFolder, file)
        fileContents[file] = await readFile(filepath, 'utf8')
        return fileContents
      }, {}))
    }