使用文件系统
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
对象具有 isFile
和 isDirectory
方法,可以使用这些方法来确定正在处理的对象的类型。
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 即可使用此训练模块。 无需知道有关容器的任何内容即可完成此训练模块。