練習 - 使用檔案系統
Tailwind Traders 在世界各地有許多實體存放區。 每天晚上,這些商店都會建立稱為 sales.json 的檔案,其中包含前一天所有銷售的總計。 這些檔案會整理到依商店識別碼命名的資料夾中。
在此練習中,您會撰寫 Node.js 程式,其可在資料夾中搜尋稱為 sales.json 的檔案。
在開發容器中開啟專案
開始在
MicrosoftDocs/node-essentials
GitHub 存放庫分的main
分支上建立新的 GitHub Codespace 的流程。在 [建立 Codespace] 頁面上,檢閱 Codespace 組態設定,然後選取 [建立新的 Codespace]
等候 Codespace 開始。 此啟動程序可能需要幾分鐘的時間。
在 Codespace 中開啟新的終端機。
驗證您的環境中已安裝 Node.js:
node --version
開發容器會使用 Node.js LTS 版本,例如
v20.5.1
。 確切的版本可能不同。此專案中的其餘練習會在此開發容器的內容中進行。
尋找 sales.json 檔案
您的工作是尋找 stores 資料夾中的所有檔案。
展開 [stores] 資料夾以及其中的每個編號資料夾。
納入 fs 模組
在
./nodejs-files
子資料夾中,建立 index.js 檔案,在編輯器中開啟。在檔案頂端,新增下列程式代碼以在 檔案中包含 fs 模組。
const fs = require("fs").promises;
接下來,建立
main
函式,這是程式代碼的進入點。 此檔案中的最後一行程式碼會叫用main
方法。const fs = require("fs").promises; async function main() {} main();
這是常見的 CommonJS 重複使用程式碼,可呼叫異步函式。
撰寫函式以尋找 sales.json
檔案
建立稱為
findSalesFiles
且接受folderName
參數的新函式。async function findSalesFiles(folderName) { // FIND SALES FILES }
在函
findSalesFiles
式內,新增下列程式代碼以完成這些工作:- (1) 在頂端新增數位,以保存程式找到的所有銷售檔案的路徑。
- (2) 使用
readdir
方法讀取 currentFolder。 - (3) 使用異步
for...of
迴圈,在方法傳readdir
回的每個專案上新增區塊以迴圈。 - (4) 新增
if
語句,以判斷專案是否為檔案或目錄。 - (5) 如果項目是目錄, 請以遞歸方式 再次呼叫 函
findSalesFiles
式,並傳入項目的路徑。 - (6) 如果不是目錄,請新增檢查以確定項目名稱符合 sales.json。
async function findSalesFiles(folderName) { // (1) Add an array at the top, to hold the paths to all the sales files that the program finds. let results = []; // (2) Read the currentFolder with the `readdir` method. const items = await fs.readdir(folderName, { withFileTypes: true }); // (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop. for (const item of items) { // (4) Add an `if` statement to determine if the item is a file or a directory. if (item.isDirectory()) { // (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item. const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`); results = results.concat(resultsReturned); } else { // (6) If it's not a directory, add a check to make sure the item name matches *sales.json*. if (item.name === "sales.json") { results.push(`${folderName}/${item.name}`); } } } return results; }
從
main
方法呼叫這個新的findSaleFiles
函式。 傳入 資料夾名稱,作為搜尋檔案的位置。async function main() { const results = await findSalesFiles("stores"); console.log(results); }
完整的應用程式看起來如下:
const fs = require("fs").promises; async function findSalesFiles(folderName) { // (1) Add an array at the top, to hold the paths to all the sales files that the program finds. let results = []; // (2) Read the currentFolder with the `readdir` method. const items = await fs.readdir(folderName, { withFileTypes: true }); // (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop. for (const item of items) { // (4) Add an `if` statement to determine if the item is a file or a directory. if (item.isDirectory()) { // (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item. const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`); results = results.concat(resultsReturned); } else { // (6) If it's not a directory, add a check to make sure the item name matches *sales.json*. if (item.name === "sales.json") { results.push(`${folderName}/${item.name}`); } } } return results; } async function main() { const results = await findSalesFiles("stores"); console.log(results); } main();
執行程式
在終端機輸入下列命令以執行程式。
node index.js
程式應該會顯示下列輸出。
[ 'stores/201/sales.json', 'stores/202/sales.json', 'stores/203/sales.json', 'stores/204/sales.json', ]
非常好! 您已成功撰寫命令列程式,其會周遊所有目錄,並在裡面尋找所有 sales.json 檔案。
然而,在此範例中建立子資料夾路徑的方式有點笨拙,因為其須要將字串串連在一起。 此外,您也可能在其他使用不同路徑分隔符號的作業系統 (例如 Windows) 上遇到問題。
在下一節中,您將了解如何使用 path 模組來建構跨作業系統運作的路徑。
遇到問題了嗎?
如果在此練習中的任何時間點遇到問題,這裡是完整的程式碼。 移除 index.js 中的所有內容,並使用此解決方案來加以取代。
const fs = require("fs").promises;
async function findSalesFiles(folderName) {
// (1) Add an array at the top, to hold the paths to all the sales files that the program finds.
let results = [];
// (2) Read the currentFolder with the `readdir` method.
const items = await fs.readdir(folderName, { withFileTypes: true });
// (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop.
for (const item of items) {
// (4) Add an `if` statement to determine if the item is a file or a directory.
if (item.isDirectory()) {
// (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item.
const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`);
results = results.concat(resultsReturned);
} else {
// (6) If it's not a directory, add a check to make sure the item name matches *sales.json*.
if (item.name === "sales.json") {
results.push(`${folderName}/${item.name}`);
}
}
}
return results;
}
async function main() {
const results = await findSalesFiles("stores");
console.log(results);
}
main();