使用文件系统

已完成

Tailwind Traders 的每个商店都将销售总额写入一个文件中,并将该文件发送到一个中心位置。 若要使用这些文件,公司需要创建可以使用文件系统的批处理进程。

现在,你将学习如何使用 Node.js 来读取文件系统,查找文件和目录。

包含“fs”模块

Node.js 提供内置模块 fs文件系统的缩写),用于处理文件系统。 由于它是 Node.js 运行时的一部分,因此无需安装它,引用它就像引用任何其他依赖项一样。

fs 模块具有 promises 命名空间,它具有所有方法的 promise 版本。 使用 promise 命名空间是使用 fs 模块的首选方法,因为它让你可以使用 async 来避免回调混乱或同步方法阻塞。

const fs = require("fs").promises;

可以使用“fs”模块对文件和目录执行多种操作。 它有几种方法可供选择。 现在,我们将重点介绍使用目录时需要了解的内容。

使用 fs.readdir 列出目录中的内容

使用“fs”模块时,经常执行的一项任务是列出或枚举目录中的内容。 例如,Tailwind Traders 有一个名为“stores”(门店)的根文件夹。 在该文件夹中,子文件夹是按门店编号组织的。 这些文件夹中是销售总额文件。 结构如下所示:

📂 stores
    📄 sales.json
    📄 totals.txt
    📂 201
    📂 202

若要通览文件夹的内容,可以使用异步的 readdir 方法。 对 fs 模块的大多数操作都有同步(后置 Sync)和异步选项。 结果按字母数字顺序返回。

const fs = require("fs").promises;

async function main() {
    const items = await fs.readdir("stores");
    console.log(items);
}
main();

项的字母数字排序列表类似于下例:

[ '201', '202', '203', '204' ]

使用 isDirectory 确定内容类型

读取目录的内容时,会以字符串数组的形式返回文件夹和文件。 可以传入 withFileTypes 选项来确定哪些字符串是文件,哪些字符串是目录。 该选项返回 Dirent 对象的数组,而不是字符串数组。 Dirent 对象具有 isFileisDirectory 方法,可以使用这些方法来确定正在处理的对象的类型。

const fs = require("fs").promises;

async function main() {
    const items = await fs.readdir("stores", { withFileTypes: true });
    for (let item of items) {
        const type = item.isDirectory() ? "folder" : "file";
        console.log(`${item.name}: ${type}`);
    }
}
main();

项的字母数字排序列表类似于下例:

201: folder
202: folder
203: folder
204: folder

有关递归的说明

通常,你可能需要使用包含多个嵌套文件夹的复杂目录结构,每个都可能包含更多子文件夹和文件。 在这种情况下,你需要一种方法来浏览这种类似于树的结构来查找特定文件。

要实现此目的,可以创建一个函数,用于标识某个项是否为文件夹。 如果是,则函数会在该文件夹中搜索更多文件。 对于找到的每个文件夹,都会重复此过程。

这是通过使用一种称为递归的技术来实现的,其中函数调用自身会在新找到的文件夹内搜索。 这样,程序就可以“遍历”整个目录树,到达每个嵌套文件夹,直到浏览完所有文件夹。

const fs = require("fs").promises;

async function findFiles(folderName) {

    let results = []

    results.push(`${folderName}`);

    const items = await fs.readdir(folderName, { withFileTypes: true });

    for (const item of items) {
        if (item.isDirectory()) {

            // RECURSION - calling the function from within itself
            const resultsReturned = await findFiles(`${folderName}/${item.name}`);
            results = results.concat(resultsReturned);
        } else {
            results.push(`${folderName}/${item.name}`);
        }
    }

    return results;
}

findFiles("stores").then((results) => console.log(results));

输出如下所示:

[
  'stores',
  'stores/201',
  'stores/201/sales.json',
  'stores/202',
  'stores/202/sales.json',
  'stores/203',
  'stores/203/sales.json',
  'stores/204',
  'stores/204/sales.json'
]

使用预定义的开发环境

此训练模块在浏览器或本地计算机中提供开发容器。 此容器提供所有需要的环境,因此无需安装 IDE 或 Node.js 即可使用此训练模块。 无需知道有关容器的任何内容即可完成此训练模块。

知识检查

1.

可以通过 fs 模块执行以下哪一项操作?