瞭解Node.js檔案系統模組 (FS)

瞭解Node.js檔案系統模組 (FS)

JavaScript 長期以來一直是最流行的指令碼語言之一,但在很長一段時間內,它並不是伺服器端後端應用程式開發的最佳選擇。後來出現了 Node.js,它用於建立使用 JavaScript 程式語言構建的伺服器端、事件驅動的輕量級應用程式。

Node.js 是一種開源 JavaScript 執行時,可在任何頂級作業系統(Windows、Mac、Linux)上免費下載和安裝。近年來,Node.js 越來越受到應用程式建立者的青睞,也為尋求一技之長的 JavaScript 開發人員提供了許多新的就業機會

在本文中,我們將學習使用 Node.js 管理檔案系統。使用 Node.js API 與檔案系統互動並執行許多複雜的操作並不費力,瞭解如何使用這些 API 將提高您的工作效率。

瞭解 Node.js 檔案系統的先決條件

首要前提是在作業系統上安裝 Node.js。Node.js 的執行不需要任何複雜的硬體,因此很容易下載並在計算機上安裝 Node.js

如果您還具備 JavaScript 的基礎知識,將有助於處理 Node.js 模組,如檔案系統(也稱為 “FS “或 “fs”)。對 JavaScript 函式、回撥函式和承諾的高階理解將幫助您更快地掌握這一主題

Node.js 檔案系統模組

處理檔案和目錄是全棧應用程式的基本需求之一。您的使用者可能希望將圖片、簡歷或其他檔案上傳到伺服器。同時,您的應用程式可能需要讀取配置檔案、移動檔案,甚至以程式設計方式更改檔案許可權。

Node.js 檔案系統模組涵蓋了所有這些功能。它提供了多個與檔案系統無縫互動的 API。大多數 API 都可通過選項和標誌進行自定義。您還可以使用它們執行同步和非同步檔案操作。

在深入瞭解檔案系統模組之前,讓我們先來了解一下 Node.js 模組。

Node.js 模組

Node.js 模組是一組作為 API 提供給使用者程式使用的功能。例如,你可以使用 fs 模組與檔案系統互動。同樣,http 模組利用其功能建立伺服器和進行更多操作。Node.js 提供了大量模組,可為您抽象出許多底層功能。

您也可以製作自己的模組。在 Node.js 14 及以後的版本中,您可以通過兩種方式建立和使用 Node.js 模組: CommonJS (CJS) 和 ESM (MJS) 模組。我們將在本文中看到的所有示例都採用 CJS 風格。

在 Node.js 中處理檔案

處理檔案涉及對檔案和目錄(資料夾)的各種操作。現在,我們將通過示例原始碼瞭解這些操作中的每一種。請開啟您最喜歡的原始碼編輯器,邊讀邊試。

首先,在原始檔中匯入 fs 模組,以便開始使用檔案系統方法。在 CJS 風格中,我們使用 require 方法從模組中匯入方法。因此,要匯入並使用 fs 模組方法,可以這樣做

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { writeFile } = require('fs/promises');
const { writeFile } = require('fs/promises');
const { writeFile } = require('fs/promises');

另外,請注意我們從 fs/promises 包中匯入了 writeFile 方法。我們希望使用 promisified 方法,因為它們是最新的方法,而且易於使用 async/await 關鍵字和較少的程式碼。其他替代方法有同步方法和回撥函式,我們稍後會看到。

如何建立和寫入檔案

建立和寫入檔案有三種方法:

  1. 使用 writeFile 方法
  2. 使用 appendFile 方法
  3. 使用 openFile 方法

這些方法接受檔案路徑和資料作為要寫入檔案的內容。如果檔案存在,它們會替換檔案中的內容。否則,它們會用這些內容建立一個新檔案。

1. 使用 writeFile 方法

下面的程式碼片段展示了 writeFile 方法的用法。首先,使用下面的程式碼片段建立一個名為 createFile.js 的檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { writeFile } = require('fs/promises');
async function writeToFile(fileName, data) {
try {
await writeFile(fileName, data);
console.log(`Wrote data to ${fileName}`);
} catch (error) {
console.error(`Got an error trying to write the file: ${error.message}`);
}
}
const { writeFile } = require('fs/promises'); async function writeToFile(fileName, data) { try { await writeFile(fileName, data); console.log(`Wrote data to ${fileName}`); } catch (error) { console.error(`Got an error trying to write the file: ${error.message}`); } }
const { writeFile } = require('fs/promises');
async function writeToFile(fileName, data) {
try {
await writeFile(fileName, data);
console.log(`Wrote data to ${fileName}`);
} catch (error) {
console.error(`Got an error trying to write the file: ${error.message}`);
}
}

請注意,我們使用 await 關鍵字來呼叫該方法,因為它會返回一個 JavaScript 承諾。成功的承諾將建立/寫入檔案。我們有一個 try-catch 塊來處理承諾被拒絕時的錯誤。

現在我們可以呼叫 writeToFile 函式了:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
writeToFile('friends.txt', 'Bob');
writeToFile('friends.txt', 'Bob');
writeToFile('friends.txt', 'Bob');

然後,開啟命令提示符或終端,使用以下命令執行上述程式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
node createFile.js
node createFile.js
node createFile.js

它將建立一個名為 friends.txt 的新檔案,其中一行簡單地寫道:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Bob
Bob
Bob

2. 使用 appendFile 方法

顧名思義,該方法的主要用途是追加和編輯檔案。不過,你也可以使用相同的方法來建立檔案。

請看下面的函式。我們使用帶有 w 標誌的 appendFile 方法來寫入檔案。追加檔案的預設標誌是 a

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { appendFile} = require('fs/promises');
async function appendToFile(fileName, data) {
try {
await appendFile(fileName, data, { flag: 'w' });
console.log(`Appended data to ${fileName}`);
} catch (error) {
console.error(`Got an error trying to append the file: {error.message}`);
}
}
const { appendFile} = require('fs/promises'); async function appendToFile(fileName, data) { try { await appendFile(fileName, data, { flag: 'w' }); console.log(`Appended data to ${fileName}`); } catch (error) { console.error(`Got an error trying to append the file: {error.message}`); } }
const { appendFile} = require('fs/promises');
async function appendToFile(fileName, data) {
try {
await appendFile(fileName, data, { flag: 'w' });
console.log(`Appended data to ${fileName}`);
} catch (error) {
console.error(`Got an error trying to append the file: {error.message}`);
}
}

現在,您可以像這樣呼叫上述函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
appendToFile('activities.txt', 'Skiing');
appendToFile('activities.txt', 'Skiing');
appendToFile('activities.txt', 'Skiing');

接下來,您可以在 Node.js 環境中使用 node 命令執行程式碼,就像我們之前看到的那樣。這將建立一個名為 activities.txt 的檔案,其中包含 Skiing 的內容。

3. 使用 open 方法

我們要學習的最後一種建立和寫入檔案的方法是 open。你可以使用 w (”寫”)標記開啟檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { open} = require('fs/promises');
async function openFile(fileName, data) {
try {
const file = await open(fileName, 'w');
await file.write(data);
console.log(`Opened file ${fileName}`);
} catch (error) {
console.error(`Got an error trying to open the file: {error.message}`);
}
}
const { open} = require('fs/promises'); async function openFile(fileName, data) { try { const file = await open(fileName, 'w'); await file.write(data); console.log(`Opened file ${fileName}`); } catch (error) { console.error(`Got an error trying to open the file: {error.message}`); } }
const { open} = require('fs/promises');
async function openFile(fileName, data) {
try {
const file = await open(fileName, 'w');
await file.write(data);
console.log(`Opened file ${fileName}`);
} catch (error) {
console.error(`Got an error trying to open the file: {error.message}`);
}
}

現在呼叫 openFile 函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
openFile('tasks.txt', 'Do homework');
openFile('tasks.txt', 'Do homework');
openFile('tasks.txt', 'Do homework');

使用 node 命令執行指令碼後,將建立一個包含初始內容的名為 tasks.txt 的檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Do homework
Do homework
Do homework

如何讀取檔案

既然我們已經知道了如何建立和寫入檔案,那就來學習讀取檔案內容吧。為此,我們將使用檔案系統模組中的 readFile 方法。

用以下程式碼建立一個名為 readThisFile.js 的檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// readThisFile.js
const { readFile } = require('fs/promises');
async function readThisFile(filePath) {
try {
const data = await readFile(filePath);
console.log(data.toString());
} catch (error) {
console.error(`Got an error trying to read the file: {error.message}`);
}
}
// readThisFile.js const { readFile } = require('fs/promises'); async function readThisFile(filePath) { try { const data = await readFile(filePath); console.log(data.toString()); } catch (error) { console.error(`Got an error trying to read the file: {error.message}`); } }
// readThisFile.js
const { readFile } = require('fs/promises');
async function readThisFile(filePath) {
try {
const data = await readFile(filePath);
console.log(data.toString());
} catch (error) {
console.error(`Got an error trying to read the file: {error.message}`);
}
}

現在,讓我們通過呼叫 readThisFile 函式來讀取我們建立的所有三個檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
readThisFile('activities.txt');
readThisFile('friends.txt');
readThisFile('tasks.txt');
readThisFile('activities.txt'); readThisFile('friends.txt'); readThisFile('tasks.txt');
readThisFile('activities.txt');
readThisFile('friends.txt');
readThisFile('tasks.txt');

最後,使用以下 node 命令執行指令碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
node readThisFile.js
node readThisFile.js
node readThisFile.js

你應該在控制檯中看到以下輸出:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Skiing
Do homework
Bob
Skiing Do homework Bob
Skiing
Do homework
Bob

這裡有一點需要注意:readFile 方法以非同步方式讀取檔案。這意味著讀取檔案的順序和在控制檯中列印響應的順序可能不一致。你必須使用同步版本的 readFile 方法才能按順序讀取檔案。稍後我們將在這裡看到這一點。

如何重新命名檔案

要重新命名檔案,請使用 fs 模組中的 rename 方法。讓我們建立一個名為 rename-me.txt 的檔案。我們將以程式設計方式重新命名該檔案。

用以下程式碼建立一個名為 renameFile.js 的檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { rename } = require('fs/promises');
async function renameFile(from, to) {
try {
await rename(from, to);
console.log(`Renamed ${from} to ${to}`);
} catch (error) {
console.error(`Got an error trying to rename the file: ${error.message}`);
}
}
const { rename } = require('fs/promises'); async function renameFile(from, to) { try { await rename(from, to); console.log(`Renamed ${from} to ${to}`); } catch (error) { console.error(`Got an error trying to rename the file: ${error.message}`); } }
const { rename } = require('fs/promises');
async function renameFile(from, to) {
try {
await rename(from, to);
console.log(`Renamed ${from} to ${to}`);
} catch (error) {
console.error(`Got an error trying to rename the file: ${error.message}`);
}
}

你可能已經注意到,重新命名方法需要兩個引數。一個是原始檔名,另一個是目標檔名。

現在讓我們呼叫上述函式來重新命名檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const oldName = "rename-me.txt";
const newName = "renamed.txt";
renameFile(oldName, newName);
const oldName = "rename-me.txt"; const newName = "renamed.txt"; renameFile(oldName, newName);
const oldName = "rename-me.txt";
const newName = "renamed.txt";
renameFile(oldName, newName);

像以前一樣,使用 node 命令執行指令碼檔案,重新命名檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
node renameFile.js
node renameFile.js
node renameFile.js

如何移動檔案

將檔案從一個目錄移動到另一個目錄與重新命名檔案路徑類似。因此,我們可以使用 rename 方法本身來移動檔案。

讓我們建立兩個資料夾:fromto。然後在 from 資料夾中建立一個名為 move-me.txt 的檔案。

接下來,我們將編寫程式碼來移動 move-me.txt 檔案。用以下程式碼段建立一個名為 moveFile.js 的檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { rename } = require('fs/promises');
const { join } = require('path');
async function moveFile(from, to) {
try {
await rename(from, to);
console.log(`Moved ${from} to ${to}`);
} catch (error) {
console.error(`Got an error trying to move the file: ${error.message}`);
}
}
const { rename } = require('fs/promises'); const { join } = require('path'); async function moveFile(from, to) { try { await rename(from, to); console.log(`Moved ${from} to ${to}`); } catch (error) { console.error(`Got an error trying to move the file: ${error.message}`); } }
const { rename } = require('fs/promises');
const { join } = require('path');
async function moveFile(from, to) {
try {
await rename(from, to);
console.log(`Moved ${from} to ${to}`);
} catch (error) {
console.error(`Got an error trying to move the file: ${error.message}`);
}
}

正如你所看到的,我們像以前一樣使用 rename 方法。但為什麼我們需要從 path 模組(是的,path 是 Node.js 的另一個重要模組)匯入 join 方法呢?

join 方法用於將多個指定的路徑段連線成一條路徑。我們將用它來形成原始檔和目標檔名的路徑:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const fromPath = join(__dirname, "from", "move-me.txt");
const destPath = join(__dirname, "to", "move-me.txt");
moveFile(fromPath, destPath);
const fromPath = join(__dirname, "from", "move-me.txt"); const destPath = join(__dirname, "to", "move-me.txt"); moveFile(fromPath, destPath);
const fromPath = join(__dirname, "from", "move-me.txt");
const destPath = join(__dirname, "to", "move-me.txt");
moveFile(fromPath, destPath);

就是這樣!如果你執行 moveFile.js 指令碼,就會看到 move-me.txt 檔案被移動到 to 資料夾。

如何複製檔案

我們使用 fs 模組中的 copyFile 方法將檔案從原始檔複製到目標檔案。

請看下面的程式碼片段:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { copyFile } = require('fs/promises');
const { join } = require('path');
async function copyAFile(from, to) {
try {
await copyFile(from, to);
console.log(`Copied ${from} to ${to}`);
} catch (err) {
console.error(`Got an error trying to copy the file: ${err.message}`);
}
}
const { copyFile } = require('fs/promises'); const { join } = require('path'); async function copyAFile(from, to) { try { await copyFile(from, to); console.log(`Copied ${from} to ${to}`); } catch (err) { console.error(`Got an error trying to copy the file: ${err.message}`); } }
const { copyFile } = require('fs/promises');
const { join } = require('path');
async function copyAFile(from, to) {
try {
await copyFile(from, to);
console.log(`Copied ${from} to ${to}`);
} catch (err) {
console.error(`Got an error trying to copy the file: ${err.message}`);
}
}

現在,您可以使用以下命令呼叫上述函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
copyAFile('friends.txt', 'friends-copy.txt');
copyAFile('friends.txt', 'friends-copy.txt');
copyAFile('friends.txt', 'friends-copy.txt');

它會將 friends.txt 的內容複製到 friends-copy.txt 檔案中。

這很好,但如何複製多個檔案呢?

您可以使用 Promise.all API 來並行執行多個承諾:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
async function copyAll(fromDir, toDir, filePaths) {
return Promise.all(filePaths.map(filePath => {
return copyAFile(join(fromDir, filePath), join(toDir, filePath));
}));
}
async function copyAll(fromDir, toDir, filePaths) { return Promise.all(filePaths.map(filePath => { return copyAFile(join(fromDir, filePath), join(toDir, filePath)); })); }
async function copyAll(fromDir, toDir, filePaths) {
return Promise.all(filePaths.map(filePath => {
return copyAFile(join(fromDir, filePath), join(toDir, filePath));
}));
}

現在,您可以提供所有檔案路徑,以便從一個目錄複製到另一個目錄:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
copyFiles('from', 'to', ['copyA.txt', 'copyB.txt']);
copyFiles('from', 'to', ['copyA.txt', 'copyB.txt']);
copyFiles('from', 'to', ['copyA.txt', 'copyB.txt']);

您還可以使用這種方法來執行其他操作,如並行移動、寫入和讀取檔案。

如何刪除檔案

我們使用 unlink 連結的方法來刪除檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { unlink } = require('fs/promises');
async function deleteFile(filePath) {
try {
await unlink(filePath);
console.log(`Deleted ${filePath}`);
} catch (error) {
console.error(`Got an error trying to delete the file: ${error.message}`);
}
}
const { unlink } = require('fs/promises'); async function deleteFile(filePath) { try { await unlink(filePath); console.log(`Deleted ${filePath}`); } catch (error) { console.error(`Got an error trying to delete the file: ${error.message}`); } }
const { unlink } = require('fs/promises');
async function deleteFile(filePath) {
try {
await unlink(filePath);
console.log(`Deleted ${filePath}`);
} catch (error) {
console.error(`Got an error trying to delete the file: ${error.message}`);
}
}

請記住,要刪除檔案,您需要提供檔案的路徑:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
deleteFile('delete-me.txt');
deleteFile('delete-me.txt');
deleteFile('delete-me.txt');

請注意,如果路徑是指向另一個檔案的符號連結,unlink 方法將取消符號連結,但原始檔案將保持不變。稍後我們將進一步討論符號連結。

如何更改檔案許可權和所有權

在某些情況下,您可能希望以程式設計方式更改檔案許可權。這對於使檔案成為只讀檔案或完全可訪問檔案非常有用。

我們將使用 chmod 方法來更改檔案許可權:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { chmod } = require('fs/promises');
async function changePermission(filePath, permission) {
try {
await chmod(filePath, permission);
console.log(`Changed permission to ${permission} for ${filePath}`);
} catch (error) {
console.error(`Got an error trying to change permission: ${error.message}`);
}
}
const { chmod } = require('fs/promises'); async function changePermission(filePath, permission) { try { await chmod(filePath, permission); console.log(`Changed permission to ${permission} for ${filePath}`); } catch (error) { console.error(`Got an error trying to change permission: ${error.message}`); } }
const { chmod } = require('fs/promises');
async function changePermission(filePath, permission) {
try {
await chmod(filePath, permission);
console.log(`Changed permission to ${permission} for ${filePath}`);
} catch (error) {
console.error(`Got an error trying to change permission: ${error.message}`);
}
}

我們可以通過檔案路徑和許可權位掩碼來更改許可權。

下面是將檔案許可權改為只讀的函式呼叫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
changePermission('permission.txt', 0o400);
changePermission('permission.txt', 0o400);
changePermission('permission.txt', 0o400);

與許可權類似,你也可以通過程式設計改變檔案的所有權。我們使用 chown 方法來實現這一功能:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { chown } = require('fs/promises');
async function changeOwnership(filePath, userId, groupId) {
try {
await chown(filePath, userId, groupId);
console.log(`Changed ownership to ${userId}:${groupId} for ${filePath}`);
} catch (error) {
console.error(`Got an error trying to change ownership: ${error.message}`);
}
}
const { chown } = require('fs/promises'); async function changeOwnership(filePath, userId, groupId) { try { await chown(filePath, userId, groupId); console.log(`Changed ownership to ${userId}:${groupId} for ${filePath}`); } catch (error) { console.error(`Got an error trying to change ownership: ${error.message}`); } }
const { chown } = require('fs/promises');
async function changeOwnership(filePath, userId, groupId) {
try {
await chown(filePath, userId, groupId);
console.log(`Changed ownership to ${userId}:${groupId} for ${filePath}`);
} catch (error) {
console.error(`Got an error trying to change ownership: ${error.message}`);
}
}

然後,我們使用檔案路徑、使用者 ID 和組 ID 呼叫該函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
changeOwnership('ownership.txt', 1000, 1010);
changeOwnership('ownership.txt', 1000, 1010);
changeOwnership('ownership.txt', 1000, 1010);

符號連結(也稱 symlink)是一個檔案系統概念,用於建立指向檔案或資料夾的連結。我們建立符號連結是為了在檔案系統中建立指向目標檔案/資料夾的快捷方式。Node.js  filesystem 模組提供了建立符號連結的 symlink 方法。

要建立符號連結,我們需要傳遞目標檔案路徑、實際檔案路徑和型別:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { symlink } = require('fs/promises');
const { join } = require('path');
async function createSymlink(target, path, type) {
try {
await symlink(target, path, type);
console.log(`Created symlink to ${target} at ${path}`);
} catch (error) {
console.error(`Got an error trying to create the symlink: ${error.message}`);
}
}
const { symlink } = require('fs/promises'); const { join } = require('path'); async function createSymlink(target, path, type) { try { await symlink(target, path, type); console.log(`Created symlink to ${target} at ${path}`); } catch (error) { console.error(`Got an error trying to create the symlink: ${error.message}`); } }
const { symlink } = require('fs/promises');
const { join } = require('path');
async function createSymlink(target, path, type) {
try {
await symlink(target, path, type);
console.log(`Created symlink to ${target} at ${path}`);
} catch (error) {
console.error(`Got an error trying to create the symlink: ${error.message}`);
}
}

我們可以用:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
createSymlink('join(__dirname, from, symMe.txt)', 'symToFile', 'file');
createSymlink('join(__dirname, from, symMe.txt)', 'symToFile', 'file');
createSymlink('join(__dirname, from, symMe.txt)', 'symToFile', 'file');

在這裡,我們建立了一個名為 symToFile 的符號連結。

如何檢視檔案的更改

你知道可以檢視檔案的更改嗎?這是一種監控更改和事件的好方法,尤其是在你意想不到的時候。你可以捕捉和稽覈這些變化,以便日後檢視。

watch 方法是觀察檔案變化的最佳方法。還有一種名為 watchFile 的替代方法,但其效能不如 watch 方法。

到目前為止,我們已經使用了帶有 async/await 關鍵字的檔案系統模組方法。讓我們通過這個例子看看 callback 函式的用法。

watch 方法接受檔案路徑和回撥函式作為引數。每當檔案發生活動時,回撥函式就會被呼叫。

我們可以利用 event 引數獲取有關活動的更多資訊:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const fs = require('fs');
function watchAFile(file) {
fs.watch(file, (event, filename) => {
console.log(`${filename} file Changed`);
});
}
const fs = require('fs'); function watchAFile(file) { fs.watch(file, (event, filename) => { console.log(`${filename} file Changed`); }); }
const fs = require('fs');
function watchAFile(file) {
fs.watch(file, (event, filename) => {
console.log(`${filename} file Changed`);
});
}

通過傳遞檔名給 watch 來呼叫函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
watchAFile('friends.txt');
watchAFile('friends.txt');
watchAFile('friends.txt');

現在,我們將自動捕獲 friends.txt 檔案中的任何活動。

在 Node.js 中處理目錄(資料夾)

現在我們來學習如何對目錄或資料夾執行操作。重新命名、移動和複製等許多操作與我們在檔案中看到的類似。不過,一些特定的方法和操作只能在目錄上使用。

如何建立目錄

我們使用 mkdir 方法建立目錄。需要將目錄名稱作為引數傳遞:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { mkdir } = require('fs/promises');
async function createDirectory(path) {
try {
await mkdir(path);
console.log(`Created directory ${path}`);
} catch (error) {
console.error(`Got an error trying to create the directory: ${error.message}`);
}
}
const { mkdir } = require('fs/promises'); async function createDirectory(path) { try { await mkdir(path); console.log(`Created directory ${path}`); } catch (error) { console.error(`Got an error trying to create the directory: ${error.message}`); } }
const { mkdir } = require('fs/promises');
async function createDirectory(path) {
try {
await mkdir(path);
console.log(`Created directory ${path}`);
} catch (error) {
console.error(`Got an error trying to create the directory: ${error.message}`);
}
}

現在,我們可以使用目錄路徑呼叫 createDirectory 函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
createDirectory('new-directory');
createDirectory('new-directory');
createDirectory('new-directory');

這將建立一個名為 new-directory 的目錄。

如何建立臨時目錄

臨時目錄不是常規目錄。它們對作業系統有特殊意義。你可以使用 mkdtemp() 方法建立臨時目錄。

讓我們在作業系統的臨時目錄中建立一個臨時資料夾。我們從 os 模組的 tmpdir() 方法中獲取臨時目錄位置的資訊:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { mkdtemp } = require('fs/promises');
const { join } = require('path');
const { tmpdir } = require('os');
async function createTemporaryDirectory(fileName) {
try {
const tempDirectory = await mkdtemp(join(tmpdir(), fileName));
console.log(`Created temporary directory ${tempDirectory}`);
} catch (error) {
console.error(`Got an error trying to create the temporary directory: ${error.message}`);
}
}
const { mkdtemp } = require('fs/promises'); const { join } = require('path'); const { tmpdir } = require('os'); async function createTemporaryDirectory(fileName) { try { const tempDirectory = await mkdtemp(join(tmpdir(), fileName)); console.log(`Created temporary directory ${tempDirectory}`); } catch (error) { console.error(`Got an error trying to create the temporary directory: ${error.message}`); } }
const { mkdtemp } = require('fs/promises');
const { join } = require('path');
const { tmpdir } = require('os');
async function createTemporaryDirectory(fileName) {
try {
const tempDirectory = await mkdtemp(join(tmpdir(), fileName));
console.log(`Created temporary directory ${tempDirectory}`);
} catch (error) {
console.error(`Got an error trying to create the temporary directory: ${error.message}`);
}
}

現在,讓我們呼叫帶有目錄名的函式來建立目錄:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
createTemporaryDirectory('node-temp-file-');
createTemporaryDirectory('node-temp-file-');
createTemporaryDirectory('node-temp-file-');

請注意,Node.js 會在建立的臨時資料夾名稱末尾新增六個隨機字元,以保持其唯一性。

如何刪除目錄

您需要使用 rmdir() 方法來刪除目錄:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { rmdir } = require('fs/promises');
async function deleteDirectory(path) {
try {
await rmdir(path);
console.log(`Deleted directory ${path}`);
} catch (error) {
console.error(`Got an error trying to delete the directory: ${error.message}`);
}
}
const { rmdir } = require('fs/promises'); async function deleteDirectory(path) { try { await rmdir(path); console.log(`Deleted directory ${path}`); } catch (error) { console.error(`Got an error trying to delete the directory: ${error.message}`); } }
const { rmdir } = require('fs/promises');
async function deleteDirectory(path) {
try {
await rmdir(path);
console.log(`Deleted directory ${path}`);
} catch (error) {
console.error(`Got an error trying to delete the directory: ${error.message}`);
}
}

接下來,通過傳遞要刪除的資料夾的路徑來呼叫上述函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
deleteDirectory('new-directory-renamed');
deleteDirectory('new-directory-renamed');
deleteDirectory('new-directory-renamed');

同步與非同步 API

到目前為止,我們已經看到了很多檔案系統方法的示例,所有這些方法都是非同步使用的。不過,您可能需要同步處理某些操作。

同步操作的一個例子就是一個接一個地讀取多個檔案。 fs 模組有一個名為 readFileSync() 的方法來完成這一操作:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const { readFileSync } = require('fs');
function readFileSynchronously(path) {
try {
const data = readFileSync(path);
console.log(data.toString());
} catch (error) {
console.error(error);
}
}
const { readFileSync } = require('fs'); function readFileSynchronously(path) { try { const data = readFileSync(path); console.log(data.toString()); } catch (error) { console.error(error); } }
const { readFileSync } = require('fs');
function readFileSynchronously(path) {
try {
const data = readFileSync(path);
console.log(data.toString());
} catch (error) {
console.error(error);
}
}

請注意,”fs/promises” 軟體包中不需要 readFileSync() 方法。這是因為該方法不是非同步的。因此,呼叫上述函式時可以使用

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
readFileSynchronously('activities.txt');
readFileSynchronously('friends.txt');
readFileSynchronously('tasks.txt');
readFileSynchronously('activities.txt'); readFileSynchronously('friends.txt'); readFileSynchronously('tasks.txt');
readFileSynchronously('activities.txt');
readFileSynchronously('friends.txt');
readFileSynchronously('tasks.txt');

在這種情況下,將按照呼叫函式的順序讀取上述所有檔案。

Node.js 檔案系統模組為其他操作(如讀取操作)提供了同步方法。請根據需要明智使用。非同步方法對並行執行更有幫助。

處理錯誤

任何程式設計師都知道,在執行檔案或目錄操作時,必須預料到錯誤並做好處理錯誤的準備。如果找不到檔案,或者沒有寫入檔案的許可權,該怎麼辦?在很多情況下,您都可能會遇到錯誤。

您應該始終在方法呼叫周圍使用 try-catch 塊。這樣,如果發生錯誤,控制將轉到 catch 塊,你可以在那裡檢視並處理錯誤。你可能已經注意到,在上面的所有示例中,我們都使用了 try-catch 塊來處理遇到的錯誤。

小結

讓我們回顧一下本教程中涉及的要點:

  • Node.js 檔案系統 (fs) 模組有許多方法可幫助完成許多底層任務。
  • 您可以執行各種檔案操作,如建立、寫入、重新命名、複製、移動、刪除等。
  • 還可以執行建立、臨時目錄、移動等多種目錄操作。
  • 所有方法都可以使用 JavaScript 承諾或回撥函式非同步呼叫。
  • 如果需要,也可以同步呼叫這些方法。
  • 與同步方法相比,非同步方法更受青睞。
  • 每次與方法互動時,使用 try-catch 塊處理錯誤。

現在,我們已經熟悉了 Node.js 檔案系統,你應該對它的來龍去脈有所瞭解。如果你想進一步加強你的專業知識,你可能想了解一下 Node.js 流,這也是學習 Node.js 模組的自然進展。流是處理資訊交換的有效方法,包括網路呼叫、檔案讀/寫等。

您可以在 GitHub 程式碼庫中找到本文使用的所有原始碼。

您是否計劃在下一個專案中使用 Node.js?請在下面的評論區告訴我們您選擇 Node.js 的原因。

評論留言