檔案系統#

穩定性:2 - 穩定

原始碼: lib/fs.js

node:fs 模組能以模擬標準 POSIX 函數的方式與檔案系統互動。

若要使用基於承諾的 API

import * as fs from 'node:fs/promises';const fs = require('node:fs/promises');

若要使用呼叫回函和同步 API

import * as fs from 'node:fs';const fs = require('node:fs');

所有檔案系統作業都有同步、呼叫回函和基於承諾的形式,且可以使用 CommonJS 語法和 ES6 模組 (ESM) 存取。

承諾範例#

基於承諾的作業會傳回一個承諾,當非同步作業完成時,該承諾會兌現。

import { unlink } from 'node:fs/promises';

try {
  await unlink('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (error) {
  console.error('there was an error:', error.message);
}const { unlink } = require('node:fs/promises');

(async function(path) {
  try {
    await unlink(path);
    console.log(`successfully deleted ${path}`);
  } catch (error) {
    console.error('there was an error:', error.message);
  }
})('/tmp/hello');

回呼範例#

回呼表單將完成回呼函式作為其最後一個引數,並非同步呼叫作業。傳遞給完成回呼的引數取決於方法,但第一個引數總是保留給例外。如果作業已順利完成,則第一個引數為 nullundefined

import { unlink } from 'node:fs';

unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});const { unlink } = require('node:fs');

unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});

當需要最大效能(在執行時間和記憶體配置兩方面)時,建議使用 node:fs 模組 API 的基於回呼的版本,而不是使用承諾 API。

同步範例#

同步 API 會封鎖 Node.js 事件迴圈和進一步的 JavaScript 執行,直到作業完成。例外會立即擲出,可以使用 try…catch 處理,或允許其冒泡。

import { unlinkSync } from 'node:fs';

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}const { unlinkSync } = require('node:fs');

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

承諾 API#

fs/promises API 提供會傳回承諾的非同步檔案系統方法。

承諾 API 使用底層 Node.js 執行緒池在事件迴圈執行緒之外執行檔案系統作業。這些作業未同步或執行緒安全。在對同一個檔案執行多個並發修改時,必須小心,否則可能會發生資料毀損。

類別:FileHandle#

<FileHandle> 物件是數字檔案描述符的物件包裝器。

<FileHandle> 物件的執行個體是由 fsPromises.open() 方法建立的。

所有 <FileHandle> 物件都是 <EventEmitter>

如果 <FileHandle> 未使用 `filehandle.close()` 方法關閉,它會嘗試自動關閉檔案描述符並發出程序警告,有助於防止記憶體外洩。請勿依賴此行為,因為它可能不可靠,且檔案可能未關閉。相反地,請務必明確關閉 <FileHandle>。Node.js 可能會在未來變更此行為。

事件:'close'#

<FileHandle> 已關閉且無法再使用時,會發出 'close' 事件。

filehandle.appendFile(data[, options])#

filehandle.writeFile() 的別名。

對檔案處理程序進行操作時,無法變更模式,模式必須與使用 fsPromises.open() 設定的模式相同。因此,這等同於 filehandle.writeFile()

filehandle.chmod(mode)#
  • mode <整數> 檔案模式位元遮罩。
  • 傳回:<Promise> 成功時會以 undefined 完成。

修改檔案的權限。請參閱 chmod(2)

filehandle.chown(uid, gid)#
  • uid <integer> 檔案的新擁有者的使用者 ID。
  • gid <integer> 檔案的新群組的群組 ID。
  • 傳回:<Promise> 成功時會以 undefined 完成。

變更檔案的所有權。用於包裝 chown(2)

filehandle.close()#
  • 傳回:<Promise> 成功時會以 undefined 完成。

在等待任何處理中的操作完成後關閉檔案處理序。

import { open } from 'node:fs/promises';

let filehandle;
try {
  filehandle = await open('thefile.txt', 'r');
} finally {
  await filehandle?.close();
} 
filehandle.createReadStream([options])#

<stream.Readable> 的預設 highWaterMark 16 KiB 不同,此方法傳回的串流有預設 highWaterMark 64 KiB。

options 可以包含 startend 值,用來從檔案讀取某個範圍的位元組,而不是整個檔案。startend 都是包含式,從 0 開始計算,允許的值範圍為 [0, Number.MAX_SAFE_INTEGER]。如果省略或未定義 startfilehandle.createReadStream() 會從目前的檔案位置開始順序讀取。encoding 可以是 <Buffer> 接受的編碼之一。

如果 FileHandle 指向僅支援封鎖讀取的字元裝置(例如鍵盤或音效卡),讀取作業會在資料可用前不會結束。這可能會阻止程序結束和串流自然關閉。

預設情況下,串流會在毀損後發出 'close' 事件。設定 emitClose 選項為 false 以變更此行為。

import { open } from 'node:fs/promises';

const fd = await open('/dev/input/event0');
// Create a stream from some character device.
const stream = fd.createReadStream();
setTimeout(() => {
  stream.close(); // This may not close the stream.
  // Artificially marking end-of-stream, as if the underlying resource had
  // indicated end-of-file by itself, allows the stream to close.
  // This does not cancel pending read operations, and if there is such an
  // operation, the process may still not be able to exit successfully
  // until it finishes.
  stream.push(null);
  stream.read(0);
}, 100); 

如果 autoClose 為 false,則即使有錯誤,檔案描述符也不會關閉。關閉檔案描述符並確保沒有檔案描述符外洩是應用程式的責任。如果 autoClose 設為 true(預設行為),則在 'error''end' 時,檔案描述符會自動關閉。

以下範例說明如何讀取長度為 100 位元組的檔案的最後 10 個位元組

import { open } from 'node:fs/promises';

const fd = await open('sample.txt');
fd.createReadStream({ start: 90, end: 99 }); 
filehandle.createWriteStream([options])#

選項 也可能包含 開始 選項,允許在檔案開頭後某個位置寫入資料,允許的值在 [0, Number.MAX_SAFE_INTEGER] 範圍內。修改檔案而不是取代檔案可能需要將 旗標 開啟 選項設定為 r+,而不是預設的 r編碼 可以是 <Buffer> 接受的任何一個編碼。

如果在 '錯誤''完成' 時將 自動關閉 設定為 true(預設行為),檔案描述符將自動關閉。如果 自動關閉 為 false,則檔案描述符不會關閉,即使有錯誤也是如此。關閉檔案描述符並確保沒有檔案描述符外洩是應用程式的責任。

預設情況下,串流會在毀損後發出 'close' 事件。設定 emitClose 選項為 false 以變更此行為。

檔案處理常式.datasync()#
  • 傳回:<Promise> 成功時會以 undefined 完成。

強制所有目前與檔案相關聯的排隊 I/O 作業轉到作業系統的同步 I/O 完成狀態。有關詳細資訊,請參閱 POSIX fdatasync(2) 文件。

檔案處理常式.sync 不同,此方法不會清除已修改的元資料。

檔案處理常式.fd#
filehandle.read(buffer, offset, length, position)#
  • buffer <Buffer> | <TypedArray> | <DataView> 將會填入讀取檔案資料的緩衝區。
  • offset <整數> 開始填入緩衝區的位置。預設:0
  • length <整數> 要讀取的位元組數。預設:buffer.byteLength - offset
  • position <整數> | <bigint> | <null> 開始從檔案讀取資料的位置。如果是 null-1,資料將從目前的檔案位置讀取,且位置會更新。如果 position 是非負整數,目前的檔案位置將保持不變。預設:: null
  • 傳回:<Promise> 成功時會履行,並傳回一個具有兩個屬性的物件

從檔案讀取資料並儲存在指定的緩衝區中。

如果檔案沒有同時修改,當讀取的位元組數為零時,表示已到檔案結尾。

filehandle.read([options])#
  • options <Object>
    • buffer <Buffer> | <TypedArray> | <DataView> 將填入已讀取檔案資料的緩衝區。預設值:Buffer.alloc(16384)
    • offset <整數> 開始填入緩衝區的位置。預設:0
    • length <整數> 要讀取的位元組數。預設:buffer.byteLength - offset
    • position <整數> | <bigint> | <null> 開始從檔案讀取資料的位置。如果是 null-1,資料將從目前的檔案位置讀取,且位置會更新。如果 position 是非負整數,目前的檔案位置將保持不變。預設:: null
  • 傳回:<Promise> 成功時會履行,並傳回一個具有兩個屬性的物件

從檔案讀取資料並儲存在指定的緩衝區中。

如果檔案沒有同時修改,當讀取的位元組數為零時,表示已到檔案結尾。

filehandle.read(buffer[, options])#
  • buffer <Buffer> | <TypedArray> | <DataView> 將會填入讀取檔案資料的緩衝區。
  • options <Object>
    • offset <整數> 開始填入緩衝區的位置。預設:0
    • length <整數> 要讀取的位元組數。預設:buffer.byteLength - offset
    • position <整數> | <bigint> | <null> 開始從檔案讀取資料的位置。如果是 null-1,資料將從目前的檔案位置讀取,且位置會更新。如果 position 是非負整數,目前的檔案位置將保持不變。預設:: null
  • 傳回:<Promise> 成功時會履行,並傳回一個具有兩個屬性的物件

從檔案讀取資料並儲存在指定的緩衝區中。

如果檔案沒有同時修改,當讀取的位元組數為零時,表示已到檔案結尾。

filehandle.readableWebStream([options])#

穩定性:1 - 實驗性質

傳回一個 ReadableStream,可用來讀取檔案資料。

如果此方法被呼叫超過一次,或者在 FileHandle 關閉或正在關閉後被呼叫,將會擲回錯誤。

import {
  open,
} from 'node:fs/promises';

const file = await open('./some/file/to/read');

for await (const chunk of file.readableWebStream())
  console.log(chunk);

await file.close();const {
  open,
} = require('node:fs/promises');

(async () => {
  const file = await open('./some/file/to/read');

  for await (const chunk of file.readableWebStream())
    console.log(chunk);

  await file.close();
})();

雖然 ReadableStream 會將檔案讀取完畢,但它不會自動關閉 FileHandle。使用者程式碼仍必須呼叫 fileHandle.close() 方法。

filehandle.readFile(options)#
  • options <物件> | <字串>
  • 傳回: <Promise> 在成功讀取檔案內容後完成。如果未指定編碼(使用 options.encoding),資料會以 <Buffer> 物件傳回。否則,資料會是字串。

非同步讀取檔案的完整內容。

如果 options 是字串,則它會指定 編碼

<FileHandle> 必須支援讀取。

如果對檔案控制代碼執行一個或多個 filehandle.read() 呼叫,然後執行 filehandle.readFile() 呼叫,資料會從目前位置讀取至檔案結尾。它並非總是從檔案開頭讀取。

filehandle.readLines([options])#

建立 readline 介面並串流檔案的便利方法。請參閱 filehandle.createReadStream() 以取得選項。

import { open } from 'node:fs/promises';

const file = await open('./some/file/to/read');

for await (const line of file.readLines()) {
  console.log(line);
}const { open } = require('node:fs/promises');

(async () => {
  const file = await open('./some/file/to/read');

  for await (const line of file.readLines()) {
    console.log(line);
  }
})();
filehandle.readv(buffers[, position])#

從檔案讀取並寫入 <ArrayBufferView> 陣列

filehandle.stat([options])#
filehandle.sync()#
  • 傳回:<Promise> 成功時會以 undefined 完成。

要求將開啟檔案描述符的所有資料沖洗到儲存裝置。具體實作取決於作業系統和裝置。有關更多詳細資訊,請參閱 POSIX fsync(2) 文件。

filehandle.truncate(len)#

截斷檔案。

如果檔案大於 len 位元組,則檔案中只會保留前 len 位元組。

以下範例只會保留檔案的前四個位元組

import { open } from 'node:fs/promises';

let filehandle = null;
try {
  filehandle = await open('temp.txt', 'r+');
  await filehandle.truncate(4);
} finally {
  await filehandle?.close();
} 

如果檔案原本小於 len 位元組,則會將檔案延伸,並用空位元組 ('\0') 填滿延伸的部分

如果 len 為負數,則會使用 0

filehandle.utimes(atime, mtime)#

變更 <FileHandle> 所引用的物件檔案系統時間戳記,然後在成功時履行承諾,且無任何引數。

filehandle.write(buffer, offset[, length[, position]])#
  • buffer <Buffer> | <TypedArray> | <DataView>
  • offset <integer> 要寫入資料的 buffer 內部開始位置。
  • length <integer> 要從 buffer 寫入的位元組數。預設:buffer.byteLength - offset
  • position <integer> | <null> 應從 buffer 寫入資料的檔案開頭的位移量。如果 position 不是 number,資料將寫入目前位置。請參閱 POSIX pwrite(2) 文件以取得更多詳細資料。預設:null
  • 傳回: <Promise>

buffer 寫入檔案。

承諾會履行,並包含兩個屬性的物件

在未等待承諾完成(或拒絕)的情況下,對同一個檔案多次使用 filehandle.write() 是不安全的。對於這種情況,請使用 filehandle.createWriteStream()

在 Linux 上,當檔案以追加模式開啟時,位置寫入無法運作。核心會忽略位置引數,並始終將資料附加到檔案的結尾。

filehandle.write(buffer[, options])#

buffer 寫入檔案。

與上述 filehandle.write 函式類似,此版本採用一個選用的 options 物件。如果未指定 options 物件,它將預設為上述值。

filehandle.write(string[, position[, encoding]])#
  • string <string>
  • position <整數> | <null> 從檔案開頭開始寫入資料的 string 的位移量。如果 position 不是 number,資料會寫入目前的位移量。請參閱 POSIX pwrite(2) 文件以取得更多詳細資訊。預設值:null
  • encoding <字串> 預期的字串編碼。預設值:'utf8'
  • 傳回: <Promise>

string 寫入檔案。如果 string 不是字串,承諾會因錯誤而遭到拒絕。

承諾會履行,並包含兩個屬性的物件

  • bytesWritten <integer> 已寫入的位元組數
  • buffer <字串> 寫入的 string 參考。

在未等待承諾完成(或拒絕)的情況下,對同一個檔案多次使用 filehandle.write() 是不安全的。對於這種情況,請使用 filehandle.createWriteStream()

在 Linux 上,當檔案以追加模式開啟時,位置寫入無法運作。核心會忽略位置引數,並始終將資料附加到檔案的結尾。

filehandle.writeFile(data, options)#

非同步將資料寫入檔案,如果檔案已存在,則取代檔案。data 可以是字串、緩衝區、<AsyncIterable><Iterable> 物件。承諾在成功時以沒有參數的方式履行。

如果 options 是字串,則它會指定 編碼

<FileHandle> 必須支援寫入。

在同一個檔案上多次使用 filehandle.writeFile() 而未等待承諾履行(或遭到拒絕)是不安全的。

如果對檔案處理呼叫一個或多個 filehandle.write(),然後呼叫 filehandle.writeFile(),資料會從目前的位移量寫入到檔案的結尾。它不會總是從檔案的開頭寫入。

filehandle.writev(buffers[, position])#

<ArrayBufferView> 陣列寫入檔案。

承諾會以包含兩個屬性的物件達成

在未等待承諾達成 (或拒絕) 前,對同一個檔案呼叫 writev() 多次是不安全的。

在 Linux 上,當檔案以附加模式開啟時,位置寫入無法運作。核心會忽略位置參數,並始終將資料附加到檔案結尾。

filehandle[Symbol.asyncDispose]()#

穩定性:1 - 實驗性質

filehandle.close() 的別名。

fsPromises.access(path[, mode])#

測試使用者對於由 path 指定的檔案或目錄的權限。mode 參數是一個可選的整數,用於指定要執行的存取檢查。mode 應為值 fs.constants.F_OK 或由 fs.constants.R_OKfs.constants.W_OKfs.constants.X_OK 的位元運算 OR 組成的遮罩(例如 fs.constants.W_OK | fs.constants.R_OK)。查看 檔案存取常數 以取得 mode 的可能值。

如果存取檢查成功,則承諾會以無值的方式履行。如果任何存取檢查失敗,則承諾會以 <Error> 物件拒絕。以下範例檢查目前程序是否可以讀取和寫入檔案 /etc/passwd

import { access, constants } from 'node:fs/promises';

try {
  await access('/etc/passwd', constants.R_OK | constants.W_OK);
  console.log('can access');
} catch {
  console.error('cannot access');
} 

不建議使用 fsPromises.access() 來檢查檔案的存取性,然後再呼叫 fsPromises.open()。這麼做會產生競爭條件,因為其他程序可能會在兩次呼叫之間變更檔案的狀態。相反地,使用者程式碼應該直接開啟/讀取/寫入檔案,並處理檔案無法存取時引發的錯誤。

fsPromises.appendFile(path, data[, options])#

非同步將資料附加到檔案,如果檔案不存在,則建立檔案。data 可以是字串或 <Buffer>

如果 options 是字串,則它會指定 編碼

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

path 可以指定為已開啟用於附加的 <FileHandle>(使用 fsPromises.open())。

fsPromises.chmod(path, mode)#

變更檔案的權限。

fsPromises.chown(path, uid, gid)#

變更檔案的所有權。

fsPromises.copyFile(src, dest[, mode])#

  • src <string> | <Buffer> | <URL> 要複製的來源檔名
  • dest <string> | <Buffer> | <URL> 複製作業的目標檔名
  • mode <integer> 指定複製作業行為的選用修改器。可以建立由兩個或更多值按位元 OR 組成的遮罩(例如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE預設值:0
    • fs.constants.COPYFILE_EXCL:如果 dest 已存在,複製操作將會失敗。
    • fs.constants.COPYFILE_FICLONE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則會使用備用複製機制。
    • fs.constants.COPYFILE_FICLONE_FORCE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則操作將會失敗。
  • 傳回:<Promise> 成功時會以 undefined 完成。

非同步地將 src 複製到 dest。預設情況下,如果 dest 已存在,它將被覆寫。

不保證複製操作的原子性。如果在打開目標檔案進行寫入後發生錯誤,系統將嘗試移除目標檔案。

import { copyFile, constants } from 'node:fs/promises';

try {
  await copyFile('source.txt', 'destination.txt');
  console.log('source.txt was copied to destination.txt');
} catch {
  console.error('The file could not be copied');
}

// By using COPYFILE_EXCL, the operation will fail if destination.txt exists.
try {
  await copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL);
  console.log('source.txt was copied to destination.txt');
} catch {
  console.error('The file could not be copied');
} 

fsPromises.cp(src, dest[, options])#

穩定性:1 - 實驗性質

  • src <string> | <URL> 要複製的來源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 取消符號連結的參考。預設值:false
    • errorOnExistforcefalse,且目標存在時,擲回錯誤。預設值:false
    • filter <Function> 用於過濾複製檔案/目錄的函式。傳回 true 以複製項目,傳回 false 以略過項目。略過目錄時,其所有內容也會被略過。也可以傳回解析為 truefalsePromise預設值:undefined
    • force <布林值> 覆寫現有的檔案或目錄。如果您將此設定為 false,且目標已存在,複製作業將會忽略錯誤。使用 errorOnExist 選項來變更此行為。預設:true
    • mode <整數> 複製作業的修改器。預設:0。請參閱 fsPromises.copyFile()mode 旗標。
    • preserveTimestamps <布林值>true 時,將保留來自 src 的時間戳記。預設:false
    • recursive <布林值> 遞迴複製目錄預設:false
    • verbatimSymlinks <布林值>true 時,將略過符號連結的的路徑解析。預設:false
  • 傳回:<Promise> 成功時會以 undefined 完成。

非同步地將整個目錄結構從 src 複製到 dest,包括子目錄和檔案。

將目錄複製到另一個目錄時,不支援 glob,且行為類似於 cp dir1/ dir2/

fsPromises.lchmod(path, mode)#

變更符號連結的權限。

此方法僅在 macOS 上實作。

fsPromises.lchown(path, uid, gid)#

變更符號連結的所有權。

fsPromises.lutimes(path, atime, mtime)#

變更檔案的存取和修改時間,方式與 fsPromises.utimes() 相同,不同之處在於如果路徑指向符號連結,則不會取消連結:而是變更符號連結本身的時間戳記。

fsPromises.link(existingPath, newPath)#

existingPathnewPath 建立新的連結。請參閱 POSIX link(2) 文件以取得更多詳細資料。

fsPromises.lstat(path[, options])#

等同於 fsPromises.stat(),除非 path 參照符號連結,否則會對連結本身執行 stat,而非其參照的檔案。請參閱 POSIX lstat(2) 文件以取得更多詳細資料。

fsPromises.mkdir(path[, options])#

非同步建立目錄。

選用的 options 參數可以是指定 mode(權限和黏著位元)的整數,或是一個物件,其中具有 mode 屬性和 recursive 屬性,表示是否應建立父目錄。當 path 是已存在的目錄時,呼叫 fsPromises.mkdir() 僅在 recursive 為 false 時才會導致拒絕。

import { mkdir } from 'node:fs/promises';

try {
  const projectFolder = new URL('./test/project/', import.meta.url);
  const createDir = await mkdir(projectFolder, { recursive: true });

  console.log(`created ${createDir}`);
} catch (err) {
  console.error(err.message);
}const { mkdir } = require('node:fs/promises');
const { join } = require('node:path');

async function makeDirectory() {
  const projectFolder = join(__dirname, 'test', 'project');
  const dirCreation = await mkdir(projectFolder, { recursive: true });

  console.log(dirCreation);
  return dirCreation;
}

makeDirectory().catch(console.error);

fsPromises.mkdtemp(prefix[, options])#

建立唯一的暫時目錄。會在提供的 prefix 結尾加上六個隨機字元來產生唯一的目錄名稱。由於平台不一致,請避免在 prefix 中使用尾隨 X 字元。某些平台(特別是 BSD)可能會傳回超過六個隨機字元,並用隨機字元取代 prefix 中的尾隨 X 字元。

選用的 options 參數可以是指定編碼的字串,或是包含指定要使用的字元編碼的 encoding 屬性的物件。

import { mkdtemp } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';

try {
  await mkdtemp(join(tmpdir(), 'foo-'));
} catch (err) {
  console.error(err);
} 

fsPromises.mkdtemp() 方法會將六個隨機選取的字元直接附加到 prefix 字串。例如,假設有一個目錄 /tmp,如果要建立一個位於 /tmp 內部的 暫時目錄,則 prefix 必須以尾隨的平台特定路徑分隔符號 (require('node:path').sep) 結尾。

fsPromises.open(path, flags[, mode])#

開啟 <FileHandle>

有關更多詳細資料,請參閱 POSIX open(2) 文件。

某些字元(< > : " / \ | ? *)在 Windows 中保留,如 命名檔案、路徑和命名空間 所述。在 NTFS 中,如果檔名包含冒號,Node.js 會開啟檔案系統串流,如 此 MSDN 頁面 所述。

fsPromises.opendir(path[, options])#

非同步開啟目錄以進行反覆掃描。有關更多詳細資料,請參閱 POSIX opendir(3) 文件。

建立一個 <fs.Dir>,其中包含所有用於從目錄中讀取和清理的進一步功能。

encoding 選項在開啟目錄和後續讀取操作時設定 path 的編碼。

使用非同步反覆運算的範例

import { opendir } from 'node:fs/promises';

try {
  const dir = await opendir('./');
  for await (const dirent of dir)
    console.log(dirent.name);
} catch (err) {
  console.error(err);
} 

使用非同步反覆運算器時,<fs.Dir> 物件在反覆運算器退出後將自動關閉。

fsPromises.readdir(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <字串> | <物件>
    • 編碼 <字串> 預設值: 'utf8'
    • withFileTypes <boolean> 預設值: false
    • recursive <boolean> 如果為 true,則遞迴讀取目錄的內容。在遞迴模式中,它將列出所有檔案、子檔案和目錄。預設值: false
  • 傳回:<Promise> 以目錄中檔案名稱的陣列為準,不包括 '.''..'

讀取目錄的內容。

選用的 options 參數可以是指定編碼的字串,或是一個物件,其中包含指定用於檔案名稱的字元編碼的 encoding 屬性。如果 encoding 設定為 'buffer',傳回的檔案名稱將傳遞為 <Buffer> 物件。

如果 options.withFileTypes 設定為 true,傳回的陣列將包含 <fs.Dirent> 物件。

import { readdir } from 'node:fs/promises';

try {
  const files = await readdir(path);
  for (const file of files)
    console.log(file);
} catch (err) {
  console.error(err);
} 

fsPromises.readFile(path[, options])#

非同步讀取檔案的完整內容。

如果未指定編碼(使用 options.encoding),資料會以 <Buffer> 物件傳回。否則,資料會是字串。

如果 options 是字串,則它會指定編碼。

path 是目錄時,fsPromises.readFile() 的行為取決於平台。在 macOS、Linux 和 Windows 上,承諾會因錯誤而遭到拒絕。在 FreeBSD 上,會傳回目錄內容的表示形式。

在執行程式碼的相同目錄中讀取 package.json 檔案的範例

import { readFile } from 'node:fs/promises';
try {
  const filePath = new URL('./package.json', import.meta.url);
  const contents = await readFile(filePath, { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}const { readFile } = require('node:fs/promises');
const { resolve } = require('node:path');
async function logFile() {
  try {
    const filePath = resolve('./package.json');
    const contents = await readFile(filePath, { encoding: 'utf8' });
    console.log(contents);
  } catch (err) {
    console.error(err.message);
  }
}
logFile();

可以使用 <AbortSignal> 中斷正在進行的 readFile。如果要求遭到中斷,傳回的承諾會因 AbortError 而遭到拒絕

import { readFile } from 'node:fs/promises';

try {
  const controller = new AbortController();
  const { signal } = controller;
  const promise = readFile(fileName, { signal });

  // Abort the request before the promise settles.
  controller.abort();

  await promise;
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
} 

中斷正在進行的要求並不會中斷個別作業系統要求,而是中斷 fs.readFile 執行的內部緩衝。

任何指定的 <FileHandle> 都必須支援讀取。

fsPromises.readlink(path[, options])#

讀取 path 參照的符號連結內容。有關更多詳細資訊,請參閱 POSIX readlink(2) 文件。成功時履行 linkString

選擇性的 options 參數可以是指定編碼的字串,或是一個物件,其中 encoding 屬性指定要使用的連結路徑字元編碼。如果 encoding 設為 'buffer',傳回的連結路徑會作為 <Buffer> 物件傳遞。

fsPromises.realpath(path[, options])#

使用與 fs.realpath.native() 函數相同的語意來判斷 path 的實際位置。

僅支援可轉換為 UTF8 字串的路徑。

選擇性的 options 參數可以是指定編碼的字串,或是一個物件,其中 encoding 屬性指定要使用的路徑字元編碼。如果 encoding 設為 'buffer',傳回的路徑會作為 <Buffer> 物件傳遞。

在 Linux 上,當 Node.js 與 musl libc 連結時,必須在 /proc 上掛載 procfs 檔案系統才能讓此函數運作。Glibc 沒有這個限制。

fsPromises.rename(oldPath, newPath)#

oldPath 重新命名為 newPath

fsPromises.rmdir(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞增等待時間重試操作,每次嘗試增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴目錄移除。在遞迴模式中,會在失敗時重試操作。預設值:false已棄用。
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100
  • 傳回:<Promise> 成功時會以 undefined 完成。

移除由 path 識別的目錄。

在檔案(而非目錄)上使用 fsPromises.rmdir() 會導致承諾在 Windows 上被拒絕,並出現 ENOENT 錯誤,而在 POSIX 上則出現 ENOTDIR 錯誤。

若要獲得類似 Unix 指令 rm -rf 的行為,請使用 fsPromises.rm() 搭配選項 { recursive: true, force: true }

fsPromises.rm(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • force <布林> 當為 true 時,如果 path 不存在,則會忽略例外。預設值:false
    • maxRetries <整數> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞減等待時間重試作業,每次嘗試會增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <布林> 如果為 true,則執行遞迴目錄移除。在遞迴模式中,作業會在失敗時重試。預設值:false
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100
  • 傳回:<Promise> 成功時會以 undefined 完成。

移除檔案和目錄(以標準 POSIX rm 工具為範本)。

fsPromises.stat(path[, options])#

fsPromises.statfs(path[, options])#

fsPromises.symlink(target, path[, type])#

建立符號連結。

type 參數僅用於 Windows 平台,且可以是 'dir''file''junction' 之一。如果 type 參數不是字串,Node.js 會自動偵測 target 類型,並使用 'file''dir'。如果 target 不存在,將會使用 'file'。Windows 交接點需要目標路徑為絕對路徑。使用 'junction' 時,target 參數會自動正規化為絕對路徑。NTFS 磁區上的交接點只能指向目錄。

fsPromises.truncate(path[, len])#

path 中內容的長度截斷(縮短或延長)為 len 位元組。

fsPromises.unlink(path)#

如果 path 參照符號連結,則移除連結,而不影響連結所參照的檔案或目錄。如果 path 參照的檔案路徑不是符號連結,則刪除檔案。有關詳細資訊,請參閱 POSIX unlink(2) 文件。

fsPromises.utimes(path, atime, mtime)#

變更 path 參照的物件的檔案系統時間戳記。

atimemtime 參數遵循以下規則

  • 值可以是表示 Unix 紀元時間的數字、Date 或數字字串,例如 '123456789.0'
  • 如果無法將值轉換為數字,或為 NaNInfinity-Infinity,則會擲回 Error

fsPromises.watch(filename[, options])#

傳回在 filename 上監控變更的非同步反覆運算器,其中 filename 是檔案或目錄。

const { watch } = require('node:fs/promises');

const ac = new AbortController();
const { signal } = ac;
setTimeout(() => ac.abort(), 10000);

(async () => {
  try {
    const watcher = watch(__filename, { signal });
    for await (const event of watcher)
      console.log(event);
  } catch (err) {
    if (err.name === 'AbortError')
      return;
    throw err;
  }
})(); 

在大部分平台上,每當目錄中出現或消失檔案名稱時,就會發出 'rename'

fs.watch() 的所有 注意事項 也適用於 fsPromises.watch()

fsPromises.writeFile(file, data[, options])#

非同步將資料寫入檔案,如果檔案已存在,則會取代該檔案。data 可以是字串、緩衝區、<AsyncIterable><Iterable> 物件。

如果 data 是緩衝區,則會忽略指定的 <FileHandle>

如果 options 是字串,則它會指定編碼。

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

任何指定的 <FileHandle> 都必須支援寫入。

在同一個檔案上多次使用 fsPromises.writeFile() 而未等到承諾解決是不安全的。

fsPromises.readFile 類似,fsPromises.writeFile 是一種便利的方法,會在內部執行多個 write 呼叫來寫入傳遞給它的緩衝區。對於效能敏感的程式碼,請考慮使用 fs.createWriteStream()filehandle.createWriteStream()

可以使用 <AbortSignal> 來取消 fsPromises.writeFile()。取消是「盡力而為」,而且仍有可能會寫入一些資料。

import { writeFile } from 'node:fs/promises';
import { Buffer } from 'node:buffer';

try {
  const controller = new AbortController();
  const { signal } = controller;
  const data = new Uint8Array(Buffer.from('Hello Node.js'));
  const promise = writeFile('message.txt', data, { signal });

  // Abort the request before the promise settles.
  controller.abort();

  await promise;
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
} 

中斷正在進行的請求不會中斷個別作業系統請求,而是會中斷 fs.writeFile 執行的內部緩衝。

fsPromises.constants#

傳回包含檔案系統操作中常用的常數的物件。此物件與 fs.constants 相同。請參閱 FS 常數 以取得更多詳細資料。

回呼 API#

回呼 API 會非同步執行所有操作,而不會阻擋事件迴圈,然後在完成或發生錯誤時呼叫回呼函式。

回呼 API 使用底層 Node.js 執行緒池在事件迴圈執行緒之外執行檔案系統操作。這些操作並非同步或執行緒安全。在對同一個檔案執行多個並發修改時,必須小心,否則可能會發生資料毀損。

fs.access(path[, mode], callback)#

測試使用者對於由 path 指定的檔案或目錄的權限。mode 參數是一個可選的整數,用於指定要執行的存取檢查。mode 應為值 fs.constants.F_OK 或由 fs.constants.R_OKfs.constants.W_OKfs.constants.X_OK 的位元運算 OR 組成的遮罩(例如 fs.constants.W_OK | fs.constants.R_OK)。查看 檔案存取常數 以取得 mode 的可能值。

最後一個參數 callback 是會呼叫可能的錯誤參數的回呼函式。如果任何可存取性檢查失敗,錯誤參數將會是 Error 物件。下列範例會檢查 package.json 是否存在,以及是否可讀或可寫。

import { access, constants } from 'node:fs';

const file = 'package.json';

// Check if the file exists in the current directory.
access(file, constants.F_OK, (err) => {
  console.log(`${file} ${err ? 'does not exist' : 'exists'}`);
});

// Check if the file is readable.
access(file, constants.R_OK, (err) => {
  console.log(`${file} ${err ? 'is not readable' : 'is readable'}`);
});

// Check if the file is writable.
access(file, constants.W_OK, (err) => {
  console.log(`${file} ${err ? 'is not writable' : 'is writable'}`);
});

// Check if the file is readable and writable.
access(file, constants.R_OK | constants.W_OK, (err) => {
  console.log(`${file} ${err ? 'is not' : 'is'} readable and writable`);
}); 

在呼叫 fs.open()fs.readFile()fs.writeFile() 之前,請勿使用 fs.access() 來檢查檔案的可存取性。這麼做會導致競爭條件,因為其他程序可能會在兩個呼叫之間變更檔案的狀態。相反地,使用者程式碼應該直接開啟/讀取/寫入檔案,並處理檔案無法存取時引發的錯誤。

撰寫(不建議)

import { access, open, close } from 'node:fs';

access('myfile', (err) => {
  if (!err) {
    console.error('myfile already exists');
    return;
  }

  open('myfile', 'wx', (err, fd) => {
    if (err) throw err;

    try {
      writeMyData(fd);
    } finally {
      close(fd, (err) => {
        if (err) throw err;
      });
    }
  });
}); 

撰寫(建議)

import { open, close } from 'node:fs';

open('myfile', 'wx', (err, fd) => {
  if (err) {
    if (err.code === 'EEXIST') {
      console.error('myfile already exists');
      return;
    }

    throw err;
  }

  try {
    writeMyData(fd);
  } finally {
    close(fd, (err) => {
      if (err) throw err;
    });
  }
}); 

讀取(不建議)

import { access, open, close } from 'node:fs';
access('myfile', (err) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('myfile does not exist');
      return;
    }

    throw err;
  }

  open('myfile', 'r', (err, fd) => {
    if (err) throw err;

    try {
      readMyData(fd);
    } finally {
      close(fd, (err) => {
        if (err) throw err;
      });
    }
  });
}); 

讀取(建議)

import { open, close } from 'node:fs';

open('myfile', 'r', (err, fd) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('myfile does not exist');
      return;
    }

    throw err;
  }

  try {
    readMyData(fd);
  } finally {
    close(fd, (err) => {
      if (err) throw err;
    });
  }
}); 

上述「不建議」的範例會檢查可存取性,然後使用檔案;「建議」的範例較佳,因為它們直接使用檔案並處理錯誤(如果有)。

一般來說,僅當檔案不會直接使用時才檢查檔案的可存取性,例如當其可存取性是來自其他程序的訊號時。

在 Windows 上,目錄上的存取控制原則 (ACL) 可能會限制對檔案或目錄的存取。但是,fs.access() 函式不會檢查 ACL,因此即使 ACL 限制使用者讀取或寫入,它也可能會報告路徑可存取。

fs.appendFile(path, data[, options], callback)#

非同步將資料附加到檔案,如果檔案不存在,則建立檔案。data 可以是字串或 <Buffer>

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

import { appendFile } from 'node:fs';

appendFile('message.txt', 'data to append', (err) => {
  if (err) throw err;
  console.log('The "data to append" was appended to file!');
}); 

如果 options 是字串,則它會指定編碼

import { appendFile } from 'node:fs';

appendFile('message.txt', 'data to append', 'utf8', callback); 

path 可以指定為已開啟用於追加的數字檔案描述符 (使用 fs.open()fs.openSync())。檔案描述符不會自動關閉。

import { open, close, appendFile } from 'node:fs';

function closeFd(fd) {
  close(fd, (err) => {
    if (err) throw err;
  });
}

open('message.txt', 'a', (err, fd) => {
  if (err) throw err;

  try {
    appendFile(fd, 'data to append', 'utf8', (err) => {
      closeFd(fd);
      if (err) throw err;
    });
  } catch (err) {
    closeFd(fd);
    throw err;
  }
}); 

fs.chmod(path, mode, callback)#

非同步變更檔案的權限。除了可能的例外情況外,不會向完成回呼提供其他引數。

請參閱 POSIX chmod(2) 文件以取得更多詳細資訊。

import { chmod } from 'node:fs';

chmod('my_file.txt', 0o775, (err) => {
  if (err) throw err;
  console.log('The permissions for file "my_file.txt" have been changed!');
}); 
檔案模式#

fs.chmod()fs.chmodSync() 方法中使用的 mode 引數是使用下列常數的邏輯 OR 建立的數字位元遮罩

常數八進位說明
fs.constants.S_IRUSR0o400由擁有者讀取
fs.constants.S_IWUSR0o200由擁有者寫入
fs.constants.S_IXUSR0o100由擁有者執行/搜尋
fs.constants.S_IRGRP0o40由群組讀取
fs.constants.S_IWGRP0o20由群組寫入
fs.constants.S_IXGRP0o10由群組執行/搜尋
fs.constants.S_IROTH0o4由其他使用者讀取
fs.constants.S_IWOTH0o2由其他使用者寫入
fs.constants.S_IXOTH0o1由其他使用者執行/搜尋

建構 mode 的較簡單方法是使用三個八進位數字的序列(例如 765)。最左邊的數字(範例中的 7)指定檔案擁有者的權限。中間的數字(範例中的 6)指定群組的權限。最右邊的數字(範例中的 5)指定其他人的權限。

數字說明
7讀取、寫入和執行
6讀取和寫入
5讀取和執行
4僅讀取
3寫入和執行
2僅寫入
1僅執行
0無權限

例如,八進位值 0o765 表示

  • 擁有者可以讀取、寫入和執行檔案。
  • 群組可以讀取和寫入檔案。
  • 其他人可以讀取和執行檔案。

在預期檔案模式的地方使用原始數字時,任何大於 0o777 的值都可能導致特定於平台的行為,而這些行為無法一致地運作。因此,fs.constants 中不會公開常數,例如 S_ISVTXS_ISGIDS_ISUID

注意事項:在 Windows 上,只能變更寫入權限,而且群組、擁有者或其他人的權限區分並未實作。

fs.chown(path, uid, gid, callback)#

非同步變更檔案的擁有者和群組。除了可能的例外情況之外,不會將任何參數傳送給完成回呼。

請參閱 POSIX chown(2) 文件以取得更多詳細資料。

fs.close(fd[, callback])#

關閉檔案描述符。除了可能的例外情況外,不會提供任何其他參數給完成回呼函式。

對任何目前透過任何其他 fs 操作使用中的檔案描述符 (fd) 呼叫 fs.close() 可能會導致未定義的行為。

請參閱 POSIX close(2) 文件以取得更多詳細資料。

fs.copyFile(src, dest[, mode], callback)#

非同步地將 src 複製到 dest。預設情況下,如果 dest 已存在,則會覆寫它。除了可能的例外情況外,不會提供任何其他參數給回呼函式。Node.js 不保證複製操作的原子性。如果在開啟目的地檔案進行寫入後發生錯誤,Node.js 會嘗試移除目的地。

mode 是指定複製操作行為的選用整數。可以建立由兩個或多個值的按位元或組成的遮罩 (例如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)。

  • fs.constants.COPYFILE_EXCL:如果 dest 已存在,複製操作將會失敗。
  • fs.constants.COPYFILE_FICLONE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則會使用備用複製機制。
  • fs.constants.COPYFILE_FICLONE_FORCE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則操作將會失敗。
import { copyFile, constants } from 'node:fs';

function callback(err) {
  if (err) throw err;
  console.log('source.txt was copied to destination.txt');
}

// destination.txt will be created or overwritten by default.
copyFile('source.txt', 'destination.txt', callback);

// By using COPYFILE_EXCL, the operation will fail if destination.txt exists.
copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL, callback); 

fs.cp(src, dest[, options], callback)#

穩定性:1 - 實驗性質

  • src <string> | <URL> 要複製的來源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 取消符號連結的參考。預設值:false
    • errorOnExistforcefalse,且目標存在時,擲回錯誤。預設值:false
    • filter <Function> 用於過濾複製檔案/目錄的函式。傳回 true 以複製項目,傳回 false 以略過項目。略過目錄時,其所有內容也會被略過。也可以傳回解析為 truefalsePromise預設值:undefined
    • force <布林值> 覆寫現有的檔案或目錄。如果您將此設定為 false,且目標已存在,複製作業將會忽略錯誤。使用 errorOnExist 選項來變更此行為。預設:true
    • mode <整數> 複製操作的修改器。預設:0。請參閱 fs.copyFile()mode 標記。
    • preserveTimestamps <布林值>true 時,將保留來自 src 的時間戳記。預設:false
    • recursive <布林值> 遞迴複製目錄預設:false
    • verbatimSymlinks <布林值>true 時,將略過符號連結的的路徑解析。預設:false
  • callback <函式>

非同步地將整個目錄結構從 src 複製到 dest,包括子目錄和檔案。

將目錄複製到另一個目錄時,不支援 glob,且行為類似於 cp dir1/ dir2/

fs.createReadStream(path[, options])#

<stream.Readable> 的預設 highWaterMark 16 KiB 不同,此方法傳回的串流有預設 highWaterMark 64 KiB。

options 可包含 startend 值,以從檔案中讀取某個位元組範圍,而不是整個檔案。startend 都是包含在內的,並且從 0 開始計算,允許的值在 [0, Number.MAX_SAFE_INTEGER] 範圍內。如果指定了 fd,而省略了 startundefined,則 fs.createReadStream() 會從目前的檔案位置順序讀取。encoding 可以是 <Buffer> 接受的任何編碼。

如果指定了 fdReadStream 會忽略 path 參數,並會使用指定的檔案描述符。這表示不會發出任何 'open' 事件。fd 應為封鎖;非封鎖 fd 應傳遞給 <net.Socket>

如果 fd 指向僅支援封鎖讀取的字元裝置(例如鍵盤或音效卡),則讀取作業會在資料可用前不會完成。這可能會阻止程序退出,並阻止串流自然關閉。

預設情況下,串流會在毀損後發出 'close' 事件。設定 emitClose 選項為 false 以變更此行為。

透過提供 fs 選項,可以覆寫對應的 fs 實作,以進行 openreadclose。在提供 fs 選項時,需要覆寫 read。如果未提供 fd,則也需要覆寫 open。如果 autoClosetrue,則也需要覆寫 close

import { createReadStream } from 'node:fs';

// Create a stream from some character device.
const stream = createReadStream('/dev/input/event0');
setTimeout(() => {
  stream.close(); // This may not close the stream.
  // Artificially marking end-of-stream, as if the underlying resource had
  // indicated end-of-file by itself, allows the stream to close.
  // This does not cancel pending read operations, and if there is such an
  // operation, the process may still not be able to exit successfully
  // until it finishes.
  stream.push(null);
  stream.read(0);
}, 100); 

如果 autoClose 為 false,則即使有錯誤,檔案描述符也不會關閉。關閉檔案描述符並確保沒有檔案描述符外洩是應用程式的責任。如果 autoClose 設為 true(預設行為),則在 'error''end' 時,檔案描述符會自動關閉。

mode 設定檔案模式(權限和黏著位元),但僅在建立檔案時才會設定。

以下範例說明如何讀取長度為 100 位元組的檔案的最後 10 個位元組

import { createReadStream } from 'node:fs';

createReadStream('sample.txt', { start: 90, end: 99 }); 

如果 options 是字串,則它會指定編碼。

fs.createWriteStream(path[, options])#

options 也可能包含一個 start 選項,允許在檔案開頭之後的某個位置寫入資料,允許的值在 [0, Number.MAX_SAFE_INTEGER] 範圍內。修改檔案而不是取代它可能需要將 flags 選項設定為 r+,而不是預設的 wencoding 可以是 <Buffer> 接受的任何一個。

如果在 '錯誤''完成' 時將 自動關閉 設定為 true(預設行為),檔案描述符將自動關閉。如果 自動關閉 為 false,則檔案描述符不會關閉,即使有錯誤也是如此。關閉檔案描述符並確保沒有檔案描述符外洩是應用程式的責任。

預設情況下,串流會在毀損後發出 'close' 事件。設定 emitClose 選項為 false 以變更此行為。

透過提供 fs 選項,可以覆寫對應的 fs 實作,包括 openwritewritevclose。在沒有 writev() 的情況下覆寫 write() 可能會降低效能,因為某些最佳化(_writev())將會停用。在提供 fs 選項時,至少需要覆寫 writewritev 其中之一。如果沒有提供 fd 選項,也需要覆寫 open。如果 autoClosetrue,也需要覆寫 close

如同 <fs.ReadStream>,如果指定了 fd<fs.WriteStream> 將會忽略 path 參數,並使用指定的檔案描述符。這表示不會發出 'open' 事件。fd 應為封鎖的;非封鎖的 fd 應傳遞給 <net.Socket>

如果 options 是字串,則它會指定編碼。

fs.exists(path, callback)#

穩定性:0 - 已棄用:改用 fs.stat()fs.access()

透過檢查檔案系統來測試給定的路徑是否存在。然後以 true 或 false 呼叫 callback 參數

import { exists } from 'node:fs';

exists('/etc/passwd', (e) => {
  console.log(e ? 'it exists' : 'no passwd!');
}); 

此回呼的參數與其他 Node.js 回呼不一致。一般來說,Node.js 回呼的第一個參數是 err 參數,後續可能會接續其他參數。fs.exists() 回呼只有一個布林值參數。這是建議使用 fs.access() 而非 fs.exists() 的原因之一。

不建議在呼叫 fs.open()fs.readFile()fs.writeFile() 之前使用 fs.exists() 檢查檔案是否存在。這麼做會產生競爭條件,因為其他程序可能會在這兩次呼叫之間變更檔案狀態。相反地,使用者程式碼應該直接開啟/讀取/寫入檔案,並處理檔案不存在時引發的錯誤。

撰寫(不建議)

import { exists, open, close } from 'node:fs';

exists('myfile', (e) => {
  if (e) {
    console.error('myfile already exists');
  } else {
    open('myfile', 'wx', (err, fd) => {
      if (err) throw err;

      try {
        writeMyData(fd);
      } finally {
        close(fd, (err) => {
          if (err) throw err;
        });
      }
    });
  }
}); 

撰寫(建議)

import { open, close } from 'node:fs';
open('myfile', 'wx', (err, fd) => {
  if (err) {
    if (err.code === 'EEXIST') {
      console.error('myfile already exists');
      return;
    }

    throw err;
  }

  try {
    writeMyData(fd);
  } finally {
    close(fd, (err) => {
      if (err) throw err;
    });
  }
}); 

讀取(不建議)

import { open, close, exists } from 'node:fs';

exists('myfile', (e) => {
  if (e) {
    open('myfile', 'r', (err, fd) => {
      if (err) throw err;

      try {
        readMyData(fd);
      } finally {
        close(fd, (err) => {
          if (err) throw err;
        });
      }
    });
  } else {
    console.error('myfile does not exist');
  }
}); 

讀取(建議)

import { open, close } from 'node:fs';

open('myfile', 'r', (err, fd) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('myfile does not exist');
      return;
    }

    throw err;
  }

  try {
    readMyData(fd);
  } finally {
    close(fd, (err) => {
      if (err) throw err;
    });
  }
}); 

上述「不建議」的範例會檢查是否存在,然後使用檔案;「建議」的範例較佳,因為它們會直接使用檔案並處理錯誤(如果有)。

一般來說,只有在不會直接使用檔案時才檢查檔案是否存在,例如當檔案的存在是來自另一個程序的訊號時。

fs.fchmod(fd, mode, callback)#

設定檔案的權限。除了可能的例外狀況外,不會提供其他參數給完成回呼。

有關更多詳細資料,請參閱 POSIX fchmod(2) 文件。

fs.fchown(fd, uid, gid, callback)#

設定檔案的所有者。除了可能的例外狀況外,不會提供其他參數給完成回呼。

有關詳細資訊,請參閱 POSIX fchown(2) 文件。

fs.fdatasync(fd, callback)#

強制將所有目前與檔案相關聯的排隊 I/O 作業傳送至作業系統的同步 I/O 完成狀態。有關詳細資訊,請參閱 POSIX fdatasync(2) 文件。除了可能的例外情況外,不會提供任何其他引數給完成回呼函式。

fs.fstat(fd[, options], callback)#

使用檔案描述符的 <fs.Stats> 呼叫回呼函式。

有關詳細資訊,請參閱 POSIX fstat(2) 文件。

fs.fsync(fd, callback)#

要求將開啟檔案描述符的所有資料沖刷至儲存裝置。具體實作取決於作業系統和裝置。有關詳細資訊,請參閱 POSIX fsync(2) 文件。除了可能的例外情況外,不會提供任何其他引數給完成回呼函式。

fs.ftruncate(fd[, len], callback)#

截斷檔案描述符。除了可能的例外情況外,不會提供任何其他引數給完成回呼函式。

有關詳細資訊,請參閱 POSIX ftruncate(2) 文件。

如果檔案描述符所引用的檔案大於 len 位元組,則檔案中只會保留前 len 位元組。

例如,下列程式只保留檔案的前四個位元組

import { open, close, ftruncate } from 'node:fs';

function closeFd(fd) {
  close(fd, (err) => {
    if (err) throw err;
  });
}

open('temp.txt', 'r+', (err, fd) => {
  if (err) throw err;

  try {
    ftruncate(fd, 4, (err) => {
      closeFd(fd);
      if (err) throw err;
    });
  } catch (err) {
    closeFd(fd);
    if (err) throw err;
  }
}); 

如果檔案原本小於 len 位元組,則會將檔案延伸,並用空位元組 ('\0') 填滿延伸的部分

如果 len 為負數,則會使用 0

fs.futimes(fd, atime, mtime, callback)#

變更由提供的檔案描述符參照的物件的檔案系統時間戳記。請參閱 fs.utimes()

fs.lchmod(path, mode, callback)#

變更符號連結的權限。除了可能的例外狀況外,不會提供其他引數給完成回呼。

此方法僅在 macOS 上實作。

請參閱 POSIX lchmod(2) 文件以取得更多詳細資料。

fs.lchown(path, uid, gid, callback)#

設定符號連結的所有者。除了可能的例外狀況外,不會提供其他引數給完成回呼。

請參閱 POSIX lchown(2) 文件以取得更多詳細資料。

fs.lutimes(path, atime, mtime, callback)#

變更檔案的存取和修改時間,方式與 fs.utimes() 相同,但差異在於,如果路徑是指符號連結,則不會取消參照連結:而是變更符號連結本身的時間戳記。

除了可能的例外狀況外,不會提供其他引數給完成回呼。

fs.link(existingPath, newPath, callback)#

existingPath 建立到 newPath 的新連結。有關詳細資訊,請參閱 POSIX link(2) 文件。除了可能的例外狀況外,不會提供任何其他引數給完成回呼函式。

fs.lstat(path[, options], callback)#

擷取路徑所指的符號連結的 <fs.Stats>。回呼函式會取得兩個引數 (err, stats),其中 stats<fs.Stats> 物件。lstat()stat() 相同,但如果 path 是符號連結,則會對連結本身執行 stat,而不是它所指的文件。

有關詳細資訊,請參閱 POSIX lstat(2) 文件。

fs.mkdir(path[, options], callback)#

非同步建立目錄。

會提供給 callback 一個可能的例外,如果 遞迴true,則會提供第一個建立的目錄路徑,(err[, 路徑])。如果未建立任何目錄(例如,如果先前已建立),則在 遞迴true 時,路徑 仍可能為 未定義

選用的 選項 引數可以是指定 模式(權限和黏著位元)的整數,或是一個具有 模式 屬性和 遞迴 屬性的物件,表示是否應建立父目錄。當 路徑 是存在的目錄時呼叫 fs.mkdir() 僅在 遞迴 為 false 時才會導致錯誤。如果 遞迴 為 false 且目錄存在,則會發生 EEXIST 錯誤。

import { mkdir } from 'node:fs';

// Create ./tmp/a/apple, regardless of whether ./tmp and ./tmp/a exist.
mkdir('./tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
}); 

在 Windows 上,即使使用遞迴,對根目錄使用 fs.mkdir() 也會導致錯誤

import { mkdir } from 'node:fs';

mkdir('/', { recursive: true }, (err) => {
  // => [Error: EPERM: operation not permitted, mkdir 'C:\']
}); 

請參閱 POSIX mkdir(2) 文件以取得更多詳細資料。

fs.mkdtemp(字首[, 選項], callback)#

建立一個唯一的暫時目錄。

產生六個隨機字元,附加在必要的 字首 後面,以建立一個唯一的暫時目錄。由於平台不一致,請避免在 字首 中使用尾隨 X 字元。一些平台,特別是 BSD,可能會傳回超過六個隨機字元,並用隨機字元取代 字首 中尾隨的 X 字元。

建立的目錄路徑會以字串傳遞給 callback 的第二個參數。

選用的 options 參數可以是指定編碼的字串,或是包含指定要使用的字元編碼的 encoding 屬性的物件。

import { mkdtemp } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';

mkdtemp(join(tmpdir(), 'foo-'), (err, directory) => {
  if (err) throw err;
  console.log(directory);
  // Prints: /tmp/foo-itXde2 or C:\Users\...\AppData\Local\Temp\foo-itXde2
}); 

fs.mkdtemp() 方法會將六個隨機選取的字元直接附加到 prefix 字串。例如,假設有一個目錄 /tmp,如果是要在 /tmp 內部 建立暫時目錄,則 prefix 必須以平台特定的路徑分隔符號 (require('node:path').sep) 作結尾。

import { tmpdir } from 'node:os';
import { mkdtemp } from 'node:fs';

// The parent directory for the new temporary directory
const tmpDir = tmpdir();

// This method is *INCORRECT*:
mkdtemp(tmpDir, (err, directory) => {
  if (err) throw err;
  console.log(directory);
  // Will print something similar to `/tmpabc123`.
  // A new temporary directory is created at the file system root
  // rather than *within* the /tmp directory.
});

// This method is *CORRECT*:
import { sep } from 'node:path';
mkdtemp(`${tmpDir}${sep}`, (err, directory) => {
  if (err) throw err;
  console.log(directory);
  // Will print something similar to `/tmp/abc123`.
  // A new temporary directory is created within
  // the /tmp directory.
}); 

fs.open(path[, flags[, mode]], callback)#

非同步檔案開啟。請參閱 POSIX open(2) 文件以取得更多詳細資料。

mode 設定檔案模式 (權限和黏著位元),但僅限於檔案已建立的情況。在 Windows 上,只能控制寫入權限;請參閱 fs.chmod()

回呼函式取得兩個引數 (err, fd)

某些字元(< > : " / \ | ? *)在 Windows 中保留,如 命名檔案、路徑和命名空間 所述。在 NTFS 中,如果檔名包含冒號,Node.js 會開啟檔案系統串流,如 此 MSDN 頁面 所述。

基於 fs.open() 的函式也展現此行為:fs.writeFile()fs.readFile() 等。

fs.openAsBlob(path[, options])#

穩定性:1 - 實驗性質

傳回一個 <Blob>,其資料由指定的檔案支援。

建立 <Blob> 後,不得修改檔案。任何修改都會導致讀取 <Blob> 資料時發生 DOMException 錯誤。在建立 Blob 時,同步檔案狀態操作,以及每次讀取前,以偵測檔案資料是否已在磁碟中修改。

import { openAsBlob } from 'node:fs';

const blob = await openAsBlob('the.file.txt');
const ab = await blob.arrayBuffer();
blob.stream();const { openAsBlob } = require('node:fs');

(async () => {
  const blob = await openAsBlob('the.file.txt');
  const ab = await blob.arrayBuffer();
  blob.stream();
})();

fs.opendir(path[, options], callback)#

非同步開啟目錄。有關更多詳細資料,請參閱 POSIX opendir(3) 文件。

建立一個 <fs.Dir>,其中包含所有用於從目錄中讀取和清理的進一步功能。

encoding 選項在開啟目錄和後續讀取操作時設定 path 的編碼。

fs.read(fd, buffer, offset, length, position, callback)#

fd 指定的檔案讀取資料。

回呼函數會收到三個引數,(err, bytesRead, buffer)

如果檔案沒有同時修改,當讀取的位元組數為零時,表示已到檔案結尾。

如果此方法呼叫為其 util.promisify() 承諾版本,它會傳回一個承諾,其中包含具有 bytesReadbuffer 屬性的 Object

fs.read(fd[, options], callback)#

類似於 fs.read() 函數,此版本採用一個選用的 options 物件。如果未指定 options 物件,它將預設為上述值。

fs.read(fd, buffer[, options], callback)#

類似於 fs.read() 函數,此版本採用一個選用的 options 物件。如果未指定 options 物件,它將預設為上述值。

fs.readdir(path[, options], callback)#

讀取目錄的內容。回呼取得兩個引數 (err, files),其中 files 是目錄中檔案名稱的陣列,不包含 '.''..'

請參閱 POSIX readdir(3) 文件以取得更多詳細資料。

選用的 options 引數可以是指定編碼的字串,或是包含 encoding 屬性的物件,用於指定傳遞給回呼的檔案名稱所使用的字元編碼。如果 encoding 設定為 'buffer',傳回的檔案名稱將傳遞為 <Buffer> 物件。

如果 options.withFileTypes 設定為 true,則 files 陣列將包含 <fs.Dirent> 物件。

fs.readFile(path[, options], callback)#

非同步讀取檔案的完整內容。

import { readFile } from 'node:fs';

readFile('/etc/passwd', (err, data) => {
  if (err) throw err;
  console.log(data);
}); 

callback 傳遞兩個參數 (err, data),其中 data 是檔案的內容。

如果未指定編碼,則傳回原始緩衝區。

如果 options 是字串,則它會指定編碼

import { readFile } from 'node:fs';

readFile('/etc/passwd', 'utf8', callback); 

當路徑為目錄時,fs.readFile()fs.readFileSync() 的行為取決於平台。在 macOS、Linux 和 Windows 上,將傳回錯誤。在 FreeBSD 上,將傳回目錄內容的表示形式。

import { readFile } from 'node:fs';

// macOS, Linux, and Windows
readFile('<directory>', (err, data) => {
  // => [Error: EISDIR: illegal operation on a directory, read <directory>]
});

//  FreeBSD
readFile('<directory>', (err, data) => {
  // => null, <data>
}); 

可以使用 AbortSignal 中止正在進行的請求。如果請求被中止,則會以 AbortError 呼叫 callback。

import { readFile } from 'node:fs';

const controller = new AbortController();
const signal = controller.signal;
readFile(fileInfo[0].name, { signal }, (err, buf) => {
  // ...
});
// When you want to abort the request
controller.abort(); 

fs.readFile() 函式會將整個檔案緩衝。為將記憶體成本降至最低,在可能的情況下,建議透過 fs.createReadStream() 串流。

中斷正在進行的要求並不會中斷個別作業系統要求,而是中斷 fs.readFile 執行的內部緩衝。

檔案描述子#
  1. 任何指定的檔案描述子都必須支援讀取。
  2. 如果將檔案描述子指定為 path,則不會自動關閉它。
  3. 讀取將從目前位置開始。例如,如果檔案已經有 'Hello World' 且使用檔案描述子讀取六個位元組,則使用相同檔案描述子呼叫 fs.readFile() 會傳回 'World',而不是 'Hello World'
效能考量#

fs.readFile() 方法會非同步地將檔案內容讀入記憶體,每次讀取一個區塊,讓事件迴圈在每個區塊之間轉換。這讓讀取作業對其他可能使用底層 libuv 執行緒池的活動影響較小,但這也表示將完整檔案讀入記憶體會花費較長的時間。

額外的讀取負擔會在不同的系統上大幅變動,而且取決於所讀取的檔案類型。如果檔案類型不是一般檔案(例如:管線),而且 Node.js 無法判斷實際檔案大小,每個讀取作業將會載入 64 KiB 的資料。對於一般檔案,每個讀取作業將會處理 512 KiB 的資料。

對於需要盡可能快速讀取檔案內容的應用程式,最好直接使用 fs.read(),並讓應用程式程式碼管理讀取檔案本身的完整內容。

Node.js GitHub 問題 #25741 提供了更多資訊,以及針對不同 Node.js 版本中多個檔案大小的 fs.readFile() 效能進行詳細分析。

fs.readlink(path[, options], callback)#

讀取 path 所指的符號連結內容。回呼函式會取得兩個參數 (err, linkString)

請參閱 POSIX readlink(2) 文件以取得更多詳細資料。

選用的 options 參數可以是指定編碼的字串,或是包含 encoding 屬性的物件,用來指定傳遞給回呼函式的連結路徑所使用的字元編碼。如果 encoding 設為 'buffer',傳回的連結路徑將會傳遞為 <Buffer> 物件。

fs.readv(fd, buffers[, position], callback)#

從由 fd 指定的檔案中讀取並使用 readv() 寫入至 ArrayBufferView 陣列。

position 是從檔案開頭開始計算的偏移量,資料應從該偏移量開始讀取。如果 typeof position !== 'number',資料將從目前位置開始讀取。

回呼函式將傳入三個參數:errbytesReadbuffersbytesRead 是從檔案中讀取的位元組數。

如果這個方法作為其 util.promisify() 承諾版本呼叫,它會傳回一個承諾,其內容為具備 bytesReadbuffers 屬性的 Object

fs.realpath(path[, options], callback)#

非同步計算標準路徑名稱,方法是解析 ... 和符號連結。

標準路徑名稱不一定是唯一的。硬連結和繫結掛載可以透過許多路徑名稱公開檔案系統實體。

這個函式會像 realpath(3) 一樣運作,但有一些例外:

  1. 在不分大小寫的檔案系統上不會執行大小寫轉換。

  2. 符號連結的最大數量與平台無關,而且通常(遠)高於原生 realpath(3) 實作支援的數量。

callback 會取得兩個引數 (err, resolvedPath)。可以使用 process.cwd 來解析相對路徑。

僅支援可轉換為 UTF8 字串的路徑。

選用的 options 引數可以是指定編碼的字串,或是一個物件,其中包含指定要傳遞給 callback 的路徑所使用的字元編碼的 encoding 屬性。如果 encoding 設為 'buffer',傳回的路徑會傳遞為 <Buffer> 物件。

如果 path 解析為 socket 或管線,函式會傳回該物件的系統相依名稱。

fs.realpath.native(path[, options], callback)#

非同步 realpath(3)

callback 會取得兩個引數 (err, resolvedPath)

僅支援可轉換為 UTF8 字串的路徑。

選用的 options 引數可以是指定編碼的字串,或是一個物件,其中包含指定要傳遞給 callback 的路徑所使用的字元編碼的 encoding 屬性。如果 encoding 設為 'buffer',傳回的路徑會傳遞為 <Buffer> 物件。

在 Linux 上,當 Node.js 與 musl libc 連結時,必須在 /proc 上掛載 procfs 檔案系統才能讓此函數運作。Glibc 沒有這個限制。

fs.rename(oldPath, newPath, callback)#

非同步將 oldPath 的檔案重新命名為 newPath 提供的路徑名稱。如果 newPath 已存在,將會覆寫它。如果 newPath 有目錄,將會產生錯誤。除了可能的例外狀況外,不會將其他引數傳遞給完成 callback。

另請參閱:rename(2)

import { rename } from 'node:fs';

rename('oldFile.txt', 'newFile.txt', (err) => {
  if (err) throw err;
  console.log('Rename complete!');
}); 

fs.rmdir(path[, options], callback)#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞增等待時間重試操作,每次嘗試增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴目錄移除。在遞迴模式中,會在失敗時重試操作。預設值:false已棄用。
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100
  • callback <函式>

非同步 rmdir(2)。除了可能的例外情況外,不會提供其他引數給完成回呼函式。

在檔案(而非目錄)上使用 fs.rmdir() 會在 Windows 上產生 ENOENT 錯誤,在 POSIX 上產生 ENOTDIR 錯誤。

若要獲得類似 Unix 指令 rm -rf 的行為,請使用 fs.rm(),並搭配選項 { recursive: true, force: true }

fs.rm(path[, options], callback)#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • force <布林> 當為 true 時,如果 path 不存在,則會忽略例外。預設值:false
    • maxRetries <整數> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞減等待時間重試作業,每次嘗試會增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴移除。在遞迴模式中,操作會在失敗時重試。預設值:false
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100
  • callback <函式>

非同步移除檔案和目錄(仿照標準 POSIX rm 實用程式)。除了可能的例外情況外,不會提供其他引數給完成回呼函式。

fs.stat(path[, options], callback)#

非同步 stat(2)。回呼函式會取得兩個引數 (err, stats),其中 stats<fs.Stats> 物件。

如果發生錯誤,err.code 將會是 常見系統錯誤 之一。

fs.stat() 會追蹤符號連結。使用 fs.lstat() 來查看連結本身。

不建議使用 fs.stat() 來檢查檔案是否存在,然後再呼叫 fs.open()fs.readFile()fs.writeFile()。相反地,使用者程式碼應該直接開啟/讀取/寫入檔案,並處理檔案不存在時引發的錯誤。

若要檢查檔案是否存在而不進行後續操作,建議使用 fs.access()

例如,假設有以下目錄結構

- txtDir
-- file.txt
- app.js 

下一個程式會檢查給定路徑的統計資料

import { stat } from 'node:fs';

const pathsToCheck = ['./txtDir', './txtDir/file.txt'];

for (let i = 0; i < pathsToCheck.length; i++) {
  stat(pathsToCheck[i], (err, stats) => {
    console.log(stats.isDirectory());
    console.log(stats);
  });
} 

產生的輸出將類似於

true
Stats {
  dev: 16777220,
  mode: 16877,
  nlink: 3,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 14214262,
  size: 96,
  blocks: 0,
  atimeMs: 1561174653071.963,
  mtimeMs: 1561174614583.3518,
  ctimeMs: 1561174626623.5366,
  birthtimeMs: 1561174126937.2893,
  atime: 2019-06-22T03:37:33.072Z,
  mtime: 2019-06-22T03:36:54.583Z,
  ctime: 2019-06-22T03:37:06.624Z,
  birthtime: 2019-06-22T03:28:46.937Z
}
false
Stats {
  dev: 16777220,
  mode: 33188,
  nlink: 1,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 14214074,
  size: 8,
  blocks: 8,
  atimeMs: 1561174616618.8555,
  mtimeMs: 1561174614584,
  ctimeMs: 1561174614583.8145,
  birthtimeMs: 1561174007710.7478,
  atime: 2019-06-22T03:36:56.619Z,
  mtime: 2019-06-22T03:36:54.584Z,
  ctime: 2019-06-22T03:36:54.584Z,
  birthtime: 2019-06-22T03:26:47.711Z
} 

fs.statfs(path[, options], callback)#

非同步 statfs(2)。傳回包含 path 的已掛載檔案系統的資訊。callback 會取得兩個參數 (err, stats),其中 stats<fs.StatFs> 物件。

如果發生錯誤,err.code 將會是 常見系統錯誤 之一。

fs.symlink(target, path[, type], callback)#

建立名為 path 的連結,指向 target。除了可能的例外狀況之外,不會將其他參數傳遞給完成 callback。

請參閱 POSIX symlink(2) 文件以取得更多詳細資訊。

type 參數僅在 Windows 上可用,且在其他平台上會被忽略。它可以設定為 'dir''file''junction'。如果 type 參數不是字串,Node.js 將自動偵測 target 類型並使用 'file''dir'。如果 target 不存在,將使用 'file'。Windows 交接點需要目標路徑為絕對路徑。使用 'junction' 時,target 參數會自動標準化為絕對路徑。NTFS 磁碟區上的交接點只能指向目錄。

相對目標相對於連結的父目錄。

import { symlink } from 'node:fs';

symlink('./mew', './mewtwo', callback); 

上述範例會建立一個符號連結 mewtwo,指向同一個目錄中的 mew

$ tree .
.
├── mew
└── mewtwo -> ./mew 

fs.truncate(path[, len], callback)#

截斷檔案。除了可能的例外情況外,不會將其他參數傳遞給完成回呼。也可以將檔案描述符傳遞為第一個參數。在這種情況下,會呼叫 fs.ftruncate()

import { truncate } from 'node:fs';
// Assuming that 'path/file.txt' is a regular file.
truncate('path/file.txt', (err) => {
  if (err) throw err;
  console.log('path/file.txt was truncated');
});const { truncate } = require('node:fs');
// Assuming that 'path/file.txt' is a regular file.
truncate('path/file.txt', (err) => {
  if (err) throw err;
  console.log('path/file.txt was truncated');
});

傳遞檔案描述符已不建議使用,未來可能會導致發生錯誤。

請參閱 POSIX truncate(2) 文件以取得更多詳細資訊。

fs.unlink(path, callback)#

非同步移除檔案或符號連結。除了可能的例外情況外,不會將其他參數傳遞給完成回呼。

import { unlink } from 'node:fs';
// Assuming that 'path/file.txt' is a regular file.
unlink('path/file.txt', (err) => {
  if (err) throw err;
  console.log('path/file.txt was deleted');
}); 

fs.unlink() 無法在目錄上執行,無論目錄是否為空。若要移除目錄,請使用 fs.rmdir()

請參閱 POSIX unlink(2) 文件以取得更多詳細資訊。

fs.unwatchFile(filename[, listener])#

停止監控 filename 的變更。如果指定 listener,則只移除該特定監聽器。否則,將移除所有監聽器,有效停止監控 filename

使用未受監控的檔案名稱呼叫 fs.unwatchFile() 是一項無操作,而不是錯誤。

使用 fs.watch()fs.watchFile()fs.unwatchFile() 更有效率。如果可能,應使用 fs.watch() 取代 fs.watchFile()fs.unwatchFile()

fs.utimes(path, atime, mtime, callback)#

變更 path 參照的物件的檔案系統時間戳記。

atimemtime 參數遵循以下規則

  • 值可以是表示 Unix 紀元時間(秒)的數字、Date 或數字字串,例如 '123456789.0'
  • 如果無法將值轉換為數字,或為 NaNInfinity-Infinity,則會擲回 Error

fs.watch(filename[, options][, listener])#

監看 filename 的變更,其中 filename 是檔案或目錄。

第二個參數是選用的。如果 options 提供為字串,它會指定 encoding。否則,options 應傳遞為物件。

監聽器回呼取得兩個參數 (eventType, filename)eventType'rename''change',而 filename 是觸發事件的檔案名稱。

在大部分平台上,每當目錄中出現或消失檔案名稱時,就會發出 'rename'

監聽器回呼附加到 <fs.FSWatcher> 觸發的 'change' 事件,但它與 eventType'change' 值不同。

如果傳遞 signal,中斷對應的 AbortController 會關閉傳回的 <fs.FSWatcher>

注意事項#

fs.watch API 在不同平台上並非 100% 一致,且在某些情況下無法使用。

在 Windows 上,如果監控的目錄被移動或重新命名,將不會發出任何事件。當監控的目錄被刪除時,會報告 EPERM 錯誤。

可用性#

此功能仰賴底層作業系統提供一種方法來接收檔案系統變更的通知。

  • 在 Linux 系統上,這會使用 inotify(7)
  • 在 BSD 系統上,這會使用 kqueue(2)
  • 在 macOS 上,這會使用 kqueue(2) 來處理檔案,並使用 FSEvents 來處理目錄。
  • 在 SunOS 系統(包括 Solaris 和 SmartOS)上,這會使用 事件埠
  • 在 Windows 系統上,此功能取決於 ReadDirectoryChangesW
  • 在 AIX 系統上,此功能取決於 AHAFS,且必須啟用。
  • 在 IBM i 系統上,不支援此功能。

如果由於某些原因而無法使用基礎功能,則 fs.watch() 將無法運作,且可能會擲回例外。例如,在網路檔案系統 (NFS、SMB 等) 或使用 Vagrant 或 Docker 等虛擬化軟體時,監視檔案或目錄可能不可靠,甚至在某些情況下無法執行。

仍然可以使用 fs.watchFile(),它使用 stat 輪詢,但此方法較慢且不可靠。

Inode#

在 Linux 和 macOS 系統上,fs.watch() 會將路徑解析為 inode,並監視 inode。如果被監視的路徑被刪除並重新建立,則會指派給它新的 inode。監視會為刪除發出事件,但會繼續監視原始 inode。不會發出新 inode 的事件。這是預期的行為。

AIX 檔案會在檔案的生命週期中保留相同的 inode。儲存並關閉 AIX 上被監視的檔案會產生兩個通知 (一個是新增新內容,另一個是截斷)。

檔案名稱引數#

僅在 Linux、macOS、Windows 和 AIX 上支援在回呼中提供 filename 引數。即使在受支援的平台上,也不總是保證提供 filename。因此,請勿假設回呼中總是提供 filename 引數,如果它為 null,請具備一些後備邏輯。

import { watch } from 'node:fs';
watch('somedir', (eventType, filename) => {
  console.log(`event type is: ${eventType}`);
  if (filename) {
    console.log(`filename provided: ${filename}`);
  } else {
    console.log('filename not provided');
  }
}); 

fs.watchFile(filename[, options], listener)#

監看 filename 的變更。每次存取檔案時,都會呼叫回呼 listener

可以省略 options 參數。如果提供,它應該是物件。options 物件可以包含一個名為 persistent 的布林,表示處理程序是否應持續執行,只要檔案持續受到監控。options 物件可以指定一個 interval 屬性,表示應以毫秒為單位輪詢目標的頻率。

listener 會取得兩個參數,目前的統計資料物件和先前的統計資料物件

import { watchFile } from 'node:fs';

watchFile('message.text', (curr, prev) => {
  console.log(`the current mtime is: ${curr.mtime}`);
  console.log(`the previous mtime was: ${prev.mtime}`);
}); 

這些統計資料物件是 fs.Stat 的執行個體。如果 bigint 選項為 true,這些物件中的數字值會指定為 BigInt

若要收到檔案修改(而非僅存取)的通知,必須比較 curr.mtimeMsprev.mtimeMs

fs.watchFile 作業導致 ENOENT 錯誤時,它會呼叫一次 listener,所有欄位都會歸零(或對於日期,則為 Unix 紀元)。如果稍後建立檔案,將會再次呼叫 listener,並傳入最新的統計資料物件。這是自 v0.10 以來功能的變更。

使用 fs.watch()fs.watchFilefs.unwatchFile 更有效率。如果可能,應使用 fs.watch 取代 fs.watchFilefs.unwatchFile

fs.watchFile() 所監控的檔案消失又重新出現時,第二次呼叫事件 (檔案重新出現) 中 previous 的內容將與第一次呼叫事件 (檔案消失) 中 previous 的內容相同。

這會發生在下列情況:

  • 檔案被刪除,然後復原
  • 檔案被重新命名,然後第二次重新命名回原本的名稱

fs.write(fd, buffer, offset[, length[, position]], callback)#

buffer 寫入 fd 指定的檔案。

offset 決定要寫入緩衝區的哪一部分,而 length 是指定要寫入位元組數目的整數。

position 指的是應該寫入此資料的檔案開頭的位移量。如果 typeof position !== 'number',資料將寫入目前的位移量。請參閱 pwrite(2)

呼叫回函會收到三個參數 (err, bytesWritten, buffer),其中 bytesWritten 指定從 buffer 寫入多少個 位元組

如果此方法以其 util.promisify() 承諾版本呼叫,它會傳回一個承諾,提供具有 bytesWrittenbuffer 屬性的 Object

在未等待回呼的情況下,不建議對同一個檔案多次使用 fs.write()。建議在這種情況下使用 fs.createWriteStream()

在 Linux 上,當檔案以附加模式開啟時,位置寫入無法運作。核心會忽略位置參數,並始終將資料附加到檔案結尾。

fs.write(fd, buffer[, options], callback)#

buffer 寫入 fd 指定的檔案。

與上述的 fs.write 函式類似,此版本採用一個選用的 options 物件。如果未指定 options 物件,則會預設為上述值。

fs.write(fd, string[, position[, encoding]], callback)#

string 寫入由 fd 指定的檔案。如果 string 不是字串,則會擲回例外。

position 指的是從檔案開頭開始計算的偏移量,資料應寫入此處。如果 typeof position !== 'number',資料會寫入目前位置。請參閱 pwrite(2)

encoding 是預期的字串編碼。

回呼將接收參數 (err, written, string),其中 written 指定傳遞字串需要的寫入位元組數。寫入位元組不一定是與寫入字串字元相同。請參閱 Buffer.byteLength

在未等待回呼的情況下,不建議對同一個檔案多次使用 fs.write()。建議在這種情況下使用 fs.createWriteStream()

在 Linux 上,當檔案以附加模式開啟時,位置寫入無法運作。核心會忽略位置參數,並始終將資料附加到檔案結尾。

在 Windows 上,如果檔案描述符連接到主控台(例如 fd == 1stdout),預設情況下,包含非 ASCII 字元的字串將無法正確呈現,無論使用哪種編碼。可以透過使用 chcp 65001 指令變更活動編碼頁,將主控台設定為正確呈現 UTF-8。請參閱 chcp 文件,以取得更多詳細資料。

fs.writeFile(file, data[, options], callback)#

file 是檔案名稱時,非同步地將資料寫入檔案,如果檔案已存在,則取代檔案。data 可以是字串或緩衝區。

file 是檔案描述子時,行為類似於直接呼叫 fs.write()(建議使用)。請參閱以下關於使用檔案描述子的注意事項。

如果 data 是緩衝區,則會忽略指定的 <FileHandle>

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

import { writeFile } from 'node:fs';
import { Buffer } from 'node:buffer';

const data = new Uint8Array(Buffer.from('Hello Node.js'));
writeFile('message.txt', data, (err) => {
  if (err) throw err;
  console.log('The file has been saved!');
}); 

如果 options 是字串,則它會指定編碼

import { writeFile } from 'node:fs';

writeFile('message.txt', 'Hello Node.js', 'utf8', callback); 

在同一個檔案上多次使用 fs.writeFile() 而又不等待回呼是不安全的。對於這種情況,建議使用 fs.createWriteStream()

類似於 fs.readFile - fs.writeFile 是一種便利的方法,它在內部執行多個 write 呼叫來寫入傳遞給它的緩衝區。對於效能敏感的程式碼,請考慮使用 fs.createWriteStream()

可以使用 <AbortSignal> 來取消 fs.writeFile()。取消是「盡力而為」,並且可能會寫入一些資料。

import { writeFile } from 'node:fs';
import { Buffer } from 'node:buffer';

const controller = new AbortController();
const { signal } = controller;
const data = new Uint8Array(Buffer.from('Hello Node.js'));
writeFile('message.txt', data, { signal }, (err) => {
  // When a request is aborted - the callback is called with an AbortError
});
// When the request should be aborted
controller.abort(); 

中斷正在進行的請求不會中斷個別作業系統請求,而是會中斷 fs.writeFile 執行的內部緩衝。

使用檔案描述子來使用 fs.writeFile()#

file 是檔案描述子時,行為幾乎與直接呼叫 fs.write() 相同,如下所示

import { write } from 'node:fs';
import { Buffer } from 'node:buffer';

write(fd, Buffer.from(data, options.encoding), callback); 

與直接呼叫 fs.write() 的不同之處在於,在某些不尋常的條件下,fs.write() 可能只會寫入緩衝區的一部分,並且需要重試才能寫入剩餘的資料,而 fs.writeFile() 會重試直到資料完全寫入(或發生錯誤)。

這方面的含義是混淆的常見來源。在檔案描述符的情況中,檔案不會被取代!資料不一定會寫入檔案的開頭,而檔案的原始資料可能會出現在新寫入資料之前和/或之後。

例如,如果連續兩次呼叫 `fs.writeFile()`,第一次寫入字串 `'Hello'`,然後寫入字串 `', World'`,檔案將包含 `'Hello, World'`,並可能包含一些檔案的原始資料(取決於原始檔案的大小和檔案描述符的位置)。如果使用檔案名稱而不是描述符,則保證檔案只包含 `', World'`。

fs.writev(fd, buffers[, position], callback)#

使用 `writev()` 將 `ArrayBufferView` 陣列寫入 `fd` 指定的檔案。

position 是應該寫入此資料的檔案開頭的偏移量。如果 `typeof position !== 'number'`,資料將寫入目前的位置。

回呼函式將提供三個引數:`err`、`bytesWritten` 和 `buffers`。`bytesWritten` 是從 `buffers` 寫入的位元組數。

如果此方法是 util.promisify() 的,它會傳回一個承諾,其中包含具有 `bytesWritten` 和 `buffers` 屬性的 `Object`。

在同一個檔案上多次使用 `fs.writev()` 而又不等待回呼函式是不安全的。對於這種情況,請使用 fs.createWriteStream()

在 Linux 上,當檔案以附加模式開啟時,位置寫入無法運作。核心會忽略位置參數,並始終將資料附加到檔案結尾。

同步 API#

同步 API 會同步執行所有操作,並在操作完成或失敗之前封鎖事件迴圈。

fs.accessSync(path[, mode])#

同步測試使用者對由 path 指定之檔案或目錄的權限。mode 參數是一個可選的整數,用於指定要執行的可存取性檢查。mode 應為值 fs.constants.F_OK 或由 fs.constants.R_OKfs.constants.W_OKfs.constants.X_OK 的任何按位元 OR 組成的遮罩(例如 fs.constants.W_OK | fs.constants.R_OK)。請查看 檔案存取常數 以取得 mode 的可能值。

如果任何可存取性檢查失敗,將會擲回 Error。否則,此方法將傳回 undefined

import { accessSync, constants } from 'node:fs';

try {
  accessSync('etc/passwd', constants.R_OK | constants.W_OK);
  console.log('can read/write');
} catch (err) {
  console.error('no access!');
} 

fs.appendFileSync(path, data[, options])#

同步將資料附加到檔案,如果檔案尚未存在,則會建立檔案。data 可以是字串或 <Buffer>

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

import { appendFileSync } from 'node:fs';

try {
  appendFileSync('message.txt', 'data to append');
  console.log('The "data to append" was appended to file!');
} catch (err) {
  /* Handle the error */
} 

如果 options 是字串,則它會指定編碼

import { appendFileSync } from 'node:fs';

appendFileSync('message.txt', 'data to append', 'utf8'); 

path 可以指定為已開啟用於追加的數字檔案描述符 (使用 fs.open()fs.openSync())。檔案描述符不會自動關閉。

import { openSync, closeSync, appendFileSync } from 'node:fs';

let fd;

try {
  fd = openSync('message.txt', 'a');
  appendFileSync(fd, 'data to append', 'utf8');
} catch (err) {
  /* Handle the error */
} finally {
  if (fd !== undefined)
    closeSync(fd);
} 

fs.chmodSync(path, mode)#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.chmod()

請參閱 POSIX chmod(2) 文件以取得更多詳細資訊。

fs.chownSync(path, uid, gid)#

同步變更檔案的所有者和群組。傳回 undefined。這是 fs.chown() 的同步版本。

請參閱 POSIX chown(2) 文件以取得更多詳細資料。

fs.closeSync(fd)#

關閉檔案描述符。傳回 undefined

對任何目前透過任何其他 fs 作業使用的檔案描述符 (fd) 呼叫 fs.closeSync() 可能會導致未定義的行為。

請參閱 POSIX close(2) 文件以取得更多詳細資料。

fs.copyFileSync(src, dest[, mode])#

同步將 src 複製到 dest。預設情況下,如果 dest 已存在,則會被覆寫。傳回 undefined。Node.js 不保證複製作業的原子性。如果在開啟目標檔案進行寫入後發生錯誤,Node.js 會嘗試移除目標檔案。

mode 是指定複製操作行為的選用整數。可以建立由兩個或多個值的按位元或組成的遮罩 (例如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)。

  • fs.constants.COPYFILE_EXCL:如果 dest 已存在,複製操作將會失敗。
  • fs.constants.COPYFILE_FICLONE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則會使用備用複製機制。
  • fs.constants.COPYFILE_FICLONE_FORCE:複製操作將嘗試建立寫入時複製的 reflink。如果平台不支援寫入時複製,則操作將會失敗。
import { copyFileSync, constants } from 'node:fs';

// destination.txt will be created or overwritten by default.
copyFileSync('source.txt', 'destination.txt');
console.log('source.txt was copied to destination.txt');

// By using COPYFILE_EXCL, the operation will fail if destination.txt exists.
copyFileSync('source.txt', 'destination.txt', constants.COPYFILE_EXCL); 

fs.cpSync(src, dest[, options])#

穩定性:1 - 實驗性質

  • src <string> | <URL> 要複製的來源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 取消符號連結的參考。預設值:false
    • errorOnExistforcefalse,且目標存在時,擲回錯誤。預設值:false
    • filter <Function> 用於過濾複製的檔案/目錄的函式。傳回 true 以複製項目,傳回 false 以忽略項目。忽略目錄時,其所有內容也會被略過。預設值: undefined
    • force <布林值> 覆寫現有的檔案或目錄。如果您將此設定為 false,且目標已存在,複製作業將會忽略錯誤。使用 errorOnExist 選項來變更此行為。預設:true
    • mode <integer> 複製作業的修改器。預設值: 0。請參閱 fs.copyFileSync()mode 旗標。
    • preserveTimestamps <布林值>true 時,將保留來自 src 的時間戳記。預設:false
    • recursive <布林值> 遞迴複製目錄預設:false
    • verbatimSymlinks <布林值>true 時,將略過符號連結的的路徑解析。預設:false

同步將整個目錄結構從 src 複製到 dest,包括子目錄和檔案。

將目錄複製到另一個目錄時,不支援 glob,且行為類似於 cp dir1/ dir2/

fs.existsSync(path)#

如果路徑存在,傳回 true,否則傳回 false

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.exists()

fs.exists() 已過時,但 fs.existsSync() 沒有。fs.exists()callback 參數接受與其他 Node.js 回呼不一致的參數。fs.existsSync() 不使用回呼。

import { existsSync } from 'node:fs';

if (existsSync('/etc/passwd'))
  console.log('The path exists.'); 

fs.fchmodSync(fd, mode)#

設定檔案的權限。傳回 undefined

有關更多詳細資料,請參閱 POSIX fchmod(2) 文件。

fs.fchownSync(fd, uid, gid)#

設定檔案的所有者。傳回 undefined

有關詳細資訊,請參閱 POSIX fchown(2) 文件。

fs.fdatasyncSync(fd)#

強制將所有目前排隊與檔案相關的 I/O 作業傳送至作業系統的同步 I/O 完成狀態。有關詳細資訊,請參閱 POSIX fdatasync(2) 說明文件。傳回 undefined

fs.fstatSync(fd[, options])#

擷取檔案描述子的 <fs.Stats>

有關詳細資訊,請參閱 POSIX fstat(2) 文件。

fs.fsyncSync(fd)#

要求將開啟檔案描述符的所有資料快取到儲存裝置。具體實作取決於作業系統和裝置。請參閱 POSIX fsync(2) 文件以取得更多詳細資訊。傳回 undefined

fs.ftruncateSync(fd[, len])#

截斷檔案描述符。傳回 undefined

如需詳細資訊,請參閱此 API 非同步版本的說明文件:fs.ftruncate()

fs.futimesSync(fd, atime, mtime)#

fs.futimes() 的同步版本。傳回 undefined

fs.lchmodSync(path, mode)#

變更符號連結的權限。傳回 undefined

此方法僅在 macOS 上實作。

請參閱 POSIX lchmod(2) 文件以取得更多詳細資料。

fs.lchownSync(path, uid, gid)#

設定路徑的所有者。傳回 undefined

請參閱 POSIX lchown(2) 文件以取得更多詳細資訊。

fs.lutimesSync(path, atime, mtime)#

變更由 path 參照的符號連結檔案系統時間戳記。傳回 undefined,或在參數不正確或操作失敗時擲回例外。這是 fs.lutimes() 的同步版本。

fs.linkSync(existingPath, newPath)#

existingPath 建立到 newPath 的新連結。請參閱 POSIX link(2) 文件以取得更多詳細資料。傳回 undefined

fs.lstatSync(path[, options])#

擷取由 path 參照的符號連結的 <fs.Stats>

有關詳細資訊,請參閱 POSIX lstat(2) 文件。

fs.mkdirSync(path[, options])#

同步建立目錄。傳回 undefined,或如果 recursivetrue,則傳回第一個建立的目錄路徑。這是 fs.mkdir() 的同步版本。

請參閱 POSIX mkdir(2) 文件以取得更多詳細資料。

fs.mkdtempSync(prefix[, options])#

傳回建立的目錄路徑。

詳細資訊,請參閱此 API 非同步版本的說明文件:fs.mkdtemp()

選用的 options 參數可以是指定編碼的字串,或是包含指定要使用的字元編碼的 encoding 屬性的物件。

fs.opendirSync(path[, options])#

同步開啟目錄。請參閱 opendir(3)

建立一個 <fs.Dir>,其中包含所有用於從目錄中讀取和清理的進一步功能。

encoding 選項在開啟目錄和後續讀取操作時設定 path 的編碼。

fs.openSync(path[, flags[, mode]])#

傳回代表檔案描述符的整數。

詳細資訊,請參閱此 API 非同步版本的說明文件:fs.open()

fs.readdirSync(path[, options])#

讀取目錄的內容。

請參閱 POSIX readdir(3) 文件以取得更多詳細資料。

選用的 options 參數可以是指定編碼的字串,或是一個物件,其中包含指定要使用於傳回檔名的字元編碼的 encoding 屬性。如果 encoding 設為 'buffer',傳回的檔名會傳遞為 <Buffer> 物件。

如果將 options.withFileTypes 設為 true,結果將包含 <fs.Dirent> 物件。

fs.readFileSync(path[, options])#

傳回 path 的內容。

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.readFile()

如果指定 encoding 選項,則此函式會傳回字串。否則會傳回緩衝區。

fs.readFile() 類似,當路徑為目錄時,fs.readFileSync() 的行為會因平台而異。

import { readFileSync } from 'node:fs';

// macOS, Linux, and Windows
readFileSync('<directory>');
// => [Error: EISDIR: illegal operation on a directory, read <directory>]

//  FreeBSD
readFileSync('<directory>'); // => <data> 

fs.readlinkSync(path[, options])#

傳回符號連結的字串值。

請參閱 POSIX readlink(2) 文件以取得更多詳細資料。

選擇性的 options 參數可以是指定編碼的字串,或是一個物件,其中 encoding 屬性指定要使用的連結路徑字元編碼。如果 encoding 設為 'buffer',傳回的連結路徑會作為 <Buffer> 物件傳遞。

fs.readSync(fd, buffer, offset, length[, position])#

傳回 bytesRead 的數量。

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.read()

fs.readSync(fd, buffer[, options])#

傳回 bytesRead 的數量。

與上述 fs.readSync 函式類似,此版本採用選用 options 物件。如果未指定 options 物件,它會預設使用上述值。

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.read()

fs.readvSync(fd, buffers[, position])#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.readv()

fs.realpathSync(path[, options])#

傳回已解析的路徑名稱。

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.realpath()

fs.realpathSync.native(path[, options])#

同步 realpath(3)

僅支援可轉換為 UTF8 字串的路徑。

選用的 options 參數可以是指定編碼的字串,或是一個物件,其 encoding 屬性指定要使用於傳回路徑的字元編碼。如果 encoding 設為 'buffer',傳回的路徑會傳遞為 <Buffer> 物件。

在 Linux 上,當 Node.js 與 musl libc 連結時,必須在 /proc 上掛載 procfs 檔案系統才能讓此函數運作。Glibc 沒有這個限制。

fs.renameSync(oldPath, newPath)#

將檔案從 oldPath 重新命名為 newPath。傳回 undefined

有關更多詳細資料,請參閱 POSIX rename(2) 說明文件。

fs.rmdirSync(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞增等待時間重試操作,每次嘗試增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴目錄移除。在遞迴模式中,會在失敗時重試操作。預設值:false已棄用。
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100

同步 rmdir(2)。傳回 undefined

在檔案(而非目錄)上使用 fs.rmdirSync() 會在 Windows 上產生 ENOENT 錯誤,在 POSIX 上產生 ENOTDIR 錯誤。

若要取得類似 Unix 指令 rm -rf 的行為,請使用 fs.rmSync() 搭配選項 { recursive: true, force: true }

fs.rmSync(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • force <布林> 當為 true 時,如果 path 不存在,則會忽略例外。預設值:false
    • maxRetries <整數> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 會以線性遞減等待時間重試作業,每次嘗試會增加 retryDelay 毫秒。此選項表示重試次數。如果 recursive 選項不是 true,則會忽略此選項。預設值:0
    • recursive <布林> 如果為 true,則執行遞迴目錄移除。在遞迴模式中,作業會在失敗時重試。預設值:false
    • retryDelay <整數> 重試之間等待的時間(毫秒)。如果 recursive 選項不是 true,則會忽略此選項。預設值:100

同步移除檔案和目錄(以標準 POSIX rm 工具為範例)。傳回 undefined

fs.statSync(path[, options])#

擷取路徑的 <fs.Stats>

fs.statfsSync(path[, options])#

同步 statfs(2)。傳回包含 path 的已掛載檔案系統資訊。

如果發生錯誤,err.code 將會是 常見系統錯誤 之一。

fs.symlinkSync(target, path[, type])#

傳回 undefined

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.symlink()

fs.truncateSync(path[, len])#

截斷檔案。傳回 undefined。也可以將檔案描述子傳遞為第一個引數。在此情況下,會呼叫 fs.ftruncateSync()

傳遞檔案描述符已不建議使用,未來可能會導致發生錯誤。

fs.unlinkSync(path)#

同步 unlink(2)。傳回 undefined

fs.utimesSync(path, atime, mtime)#

傳回 undefined

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.utimes()

fs.writeFileSync(file, data[, options])#

傳回 undefined

mode 選項僅影響新建立的檔案。請參閱 fs.open() 以取得更多詳細資料。

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.writeFile()

fs.writeSync(fd, buffer, offset[, length[, position]])#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.write(fd, buffer...)

fs.writeSync(fd, buffer[, options])#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.write(fd, buffer...)

fs.writeSync(fd, string[, position[, encoding]])#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.write(fd, string...)

fs.writevSync(fd, buffers[, position])#

有關詳細資訊,請參閱此 API 非同步版本的說明文件:fs.writev()

共用物件#

共用物件由所有檔案系統 API 變體(承諾、回呼和同步)共用。

類別:fs.Dir#

代表目錄串流的類別。

fs.opendir()fs.opendirSync()fsPromises.opendir() 建立。

import { opendir } from 'node:fs/promises';

try {
  const dir = await opendir('./');
  for await (const dirent of dir)
    console.log(dirent.name);
} catch (err) {
  console.error(err);
} 

使用非同步反覆運算器時,<fs.Dir> 物件在反覆運算器退出後將自動關閉。

dir.close()#

非同步關閉目錄的底層資源處理。後續讀取將導致錯誤。

傳回一個承諾,在資源關閉後會履行。

dir.close(callback)#

非同步關閉目錄的底層資源處理。後續讀取將導致錯誤。

資源處理程序關閉後,將呼叫 callback

dir.closeSync()#

同步關閉目錄的底層資源處理程序。後續讀取將導致錯誤。

dir.path#

此目錄的唯讀路徑,如提供給 fs.opendir()fs.opendirSync()fsPromises.opendir()

dir.read()#

非同步讀取下一個目錄項目,透過 readdir(3) 作為 <fs.Dirent>

傳回一個 Promise,將以 <fs.Dirent> 履行,或在沒有更多目錄項目可讀取時傳回 null

此函式傳回的目錄項目沒有特定順序,由作業系統的底層目錄機制提供。在反覆處理目錄時新增或移除的項目可能不會包含在反覆處理結果中。

dir.read(callback)#

非同步讀取下一個目錄項目,透過 readdir(3) 作為 <fs.Dirent>

讀取完成後,callback 會呼叫 <fs.Dirent>,如果沒有更多目錄項目可讀取,則呼叫 null

此函式傳回的目錄項目沒有特定順序,由作業系統的底層目錄機制提供。在反覆處理目錄時新增或移除的項目可能不會包含在反覆處理結果中。

dir.readSync()#

同步讀取下一個目錄項目,為 <fs.Dirent>。如需更多詳細資料,請參閱 POSIX readdir(3) 文件。

如果沒有更多目錄項目可讀取,則會傳回 null

此函式傳回的目錄項目沒有特定順序,由作業系統的底層目錄機制提供。在反覆處理目錄時新增或移除的項目可能不會包含在反覆處理結果中。

dir[Symbol.asyncIterator]()#

非同步迭代目錄,直到所有項目都已讀取。如需更多詳細資料,請參閱 POSIX readdir(3) 文件。

非同步迭代器傳回的項目永遠是 <fs.Dirent>dir.read()null 案例會在內部處理。

請參閱 <fs.Dir> 以取得範例。

此迭代器傳回的目錄項目沒有特定順序,由作業系統的底層目錄機制提供。在迭代目錄時新增或移除的項目可能不會包含在迭代結果中。

類別:fs.Dirent#

目錄條目的表示,可以是檔案或目錄內的子目錄,由從 <fs.Dir> 讀取回傳。目錄條目是檔案名稱和檔案類型配對的組合。

此外,當 fs.readdir()fs.readdirSync() 被呼叫,且 withFileTypes 選項設為 true 時,產生的陣列會填入 <fs.Dirent> 物件,而不是字串或 <Buffer>

dirent.isBlockDevice()#

如果 <fs.Dirent> 物件描述區塊裝置,則回傳 true

dirent.isCharacterDevice()#

如果 <fs.Dirent> 物件描述字元裝置,則回傳 true

dirent.isDirectory()#

如果 <fs.Dirent> 物件描述檔案系統目錄,則回傳 true

dirent.isFIFO()#

如果 <fs.Dirent> 物件描述先進先出 (FIFO) 管道,則回傳 true

dirent.isFile()#

如果 <fs.Dirent> 物件描述一般檔案,則回傳 true

dirent.isSocket()#

如果 <fs.Dirent> 物件描述一個 socket,則傳回 true

dirent.isSymbolicLink()#

如果 <fs.Dirent> 物件描述一個符號連結,則傳回 true

dirent.name#

這個 <fs.Dirent> 物件所指的文件名稱。這個值的類型是由傳遞給 fs.readdir()fs.readdirSync()options.encoding 所決定的。

dirent.parentPath#

穩定性:1 – 實驗性

這個 <fs.Dirent> 物件所指的文件的父目錄路徑。

dirent.path#

穩定性:0 - 已棄用:改用 dirent.parentPath

dirent.parentPath 的別名。

類別:fs.FSWatcher#

成功呼叫 fs.watch() 方法會傳回一個新的 <fs.FSWatcher> 物件。

所有 <fs.FSWatcher> 物件都會在特定監控檔案被修改時發出 'change' 事件。

事件:'change'#
  • eventType <string> 發生變更事件的類型
  • filename <string> | <Buffer> 已變更的檔案名稱(如果相關/可用)

在監控的目錄或檔案中發生變更時發出。請參閱 fs.watch() 中的更多詳細資訊。

filename 參數可能不會提供,具體取決於作業系統支援。如果提供 filename,如果 fs.watch() 被呼叫且其 encoding 選項設定為 'buffer',則會提供為 <Buffer>;否則 filename 會是 UTF-8 字串。

import { watch } from 'node:fs';
// Example when handled through fs.watch() listener
watch('./tmp', { encoding: 'buffer' }, (eventType, filename) => {
  if (filename) {
    console.log(filename);
    // Prints: <Buffer ...>
  }
}); 
事件:'close'#

在監控器停止監控變更時發出。已關閉的 <fs.FSWatcher> 物件在事件處理常式中不再可用。

事件:'error'#

在監控檔案時發生錯誤時發出。已出錯的 <fs.FSWatcher> 物件在事件處理常式中不再可用。

watcher.close()#

停止觀察給定的 <fs.FSWatcher> 上的變更。一旦停止,<fs.FSWatcher> 物件便不再可用。

watcher.ref()#

呼叫時,要求 Node.js 事件迴圈在 <fs.FSWatcher> 處於活動狀態時退出。多次呼叫 watcher.ref() 將不會產生任何效果。

預設情況下,所有 <fs.FSWatcher> 物件都已「ref」,因此通常不需要呼叫 watcher.ref(),除非先前已呼叫 watcher.unref()

watcher.unref()#

呼叫時,活動的 <fs.FSWatcher> 物件將不需要 Node.js 事件迴圈保持活動狀態。如果沒有其他活動讓事件迴圈繼續執行,則處理程序可能會在呼叫 <fs.FSWatcher> 物件的回呼函式之前結束。多次呼叫 watcher.unref() 將不會產生任何效果。

類別:fs.StatWatcher#

成功呼叫 fs.watchFile() 方法將傳回新的 <fs.StatWatcher> 物件。

watcher.ref()#

呼叫時,要求 Node.js 事件迴圈在 <fs.StatWatcher> 處於活動狀態時退出。多次呼叫 watcher.ref() 將不會產生任何效果。

預設情況下,所有 <fs.StatWatcher> 物件都已「ref」,因此通常不需要呼叫 watcher.ref(),除非先前已呼叫 watcher.unref()

watcher.unref()#

呼叫時,活動的 <fs.StatWatcher> 物件將不需要 Node.js 事件迴圈保持活動狀態。如果沒有其他活動讓事件迴圈繼續執行,則處理程序可能會在呼叫 <fs.StatWatcher> 物件的回呼函式之前結束。多次呼叫 watcher.unref() 將不會產生任何效果。

類別:fs.ReadStream#

<fs.ReadStream> 的執行個體使用 fs.createReadStream() 函數建立並傳回。

事件:'close'#

<fs.ReadStream> 的基礎檔案描述已關閉時發出。

事件:'open'#

<fs.ReadStream> 的檔案描述已開啟時發出。

事件:'ready'#

<fs.ReadStream> 準備好使用時發出。

'open' 之後立即觸發。

readStream.bytesRead#

迄今已讀取的位元組數。

readStream.path#

串流正在讀取的檔案路徑,如 fs.createReadStream() 的第一個引數所指定。如果 path 作為字串傳遞,則 readStream.path 會是字串。如果 path 作為 <Buffer> 傳遞,則 readStream.path 會是 <Buffer>。如果指定 fd,則 readStream.path 會是 undefined

readStream.pending#

如果基礎檔案尚未開啟,則此屬性為 true,即在發出 'ready' 事件之前。

類別:fs.Stats#

一個 <fs.Stats> 物件提供有關檔案的資訊。

fs.stat()fs.lstat()fs.fstat() 和其同步對應項傳回的物件屬於此類型。如果傳遞給這些方法的 options 中的 bigint 為 true,則數值會是 bigint 而不是 number,而且物件會包含附加的 nanosecond 精確度屬性,其後綴為 Ns

Stats {
  dev: 2114,
  ino: 48064969,
  mode: 33188,
  nlink: 1,
  uid: 85,
  gid: 100,
  rdev: 0,
  size: 527,
  blksize: 4096,
  blocks: 8,
  atimeMs: 1318289051000.1,
  mtimeMs: 1318289051000.1,
  ctimeMs: 1318289051000.1,
  birthtimeMs: 1318289051000.1,
  atime: Mon, 10 Oct 2011 23:24:11 GMT,
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT } 

bigint 版本

BigIntStats {
  dev: 2114n,
  ino: 48064969n,
  mode: 33188n,
  nlink: 1n,
  uid: 85n,
  gid: 100n,
  rdev: 0n,
  size: 527n,
  blksize: 4096n,
  blocks: 8n,
  atimeMs: 1318289051000n,
  mtimeMs: 1318289051000n,
  ctimeMs: 1318289051000n,
  birthtimeMs: 1318289051000n,
  atimeNs: 1318289051000000000n,
  mtimeNs: 1318289051000000000n,
  ctimeNs: 1318289051000000000n,
  birthtimeNs: 1318289051000000000n,
  atime: Mon, 10 Oct 2011 23:24:11 GMT,
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT } 
stats.isBlockDevice()#

如果 <fs.Stats> 物件描述區塊裝置,則傳回 true

stats.isCharacterDevice()#

如果 <fs.Stats> 物件描述字元裝置,則傳回 true

stats.isDirectory()#

如果 <fs.Stats> 物件描述檔案系統目錄,則傳回 true

如果 <fs.Stats> 物件是透過呼叫 fs.lstat() 符號連結(解析為目錄)取得,此方法會傳回 false。這是因為 fs.lstat() 會傳回符號連結本身的資訊,而不是它解析的路徑。

stats.isFIFO()#

如果 <fs.Stats> 物件描述先進先出 (FIFO) 管道,會傳回 true

stats.isFile()#

如果 <fs.Stats> 物件描述一般檔案,會傳回 true

stats.isSocket()#

如果 <fs.Stats> 物件描述 socket,會傳回 true

stats.isSymbolicLink()#

如果 <fs.Stats> 物件描述符號連結,會傳回 true

此方法僅在使用 fs.lstat() 時有效。

stats.dev#

包含檔案的裝置的數字識別碼。

stats.ino#

檔案系統特定檔案的「Inode」編號。

stats.mode#

描述檔案類型和模式的位元欄位。

stats.nlink#

檔案存在的硬連結數目。

stats.uid#

擁有該檔案的使用者之數值使用者識別碼 (POSIX)。

stats.gid#

擁有該檔案的群組之數值群組識別碼 (POSIX)。

stats.rdev#

如果檔案表示裝置,則為數值裝置識別碼。

stats.size#

檔案大小(以位元組為單位)。

如果底層檔案系統不支援取得檔案大小,則此值會為 0

stats.blksize#

檔案系統區塊大小,用於 I/O 作業。

stats.blocks#

為此檔案配置的區塊數目。

stats.atimeMs#

表示自 POSIX Epoch 以來,存取此檔案的最後時間戳記,以毫秒為單位。

stats.mtimeMs#

表示自 POSIX Epoch 以來,修改此檔案的最後時間戳記,以毫秒為單位。

stats.ctimeMs#

表示自 POSIX Epoch 以來,變更檔案狀態的最後時間戳記,以毫秒為單位。

stats.birthtimeMs#

表示建立此檔案的時間戳記,以毫秒為單位。

stats.atimeNs#

僅在將 bigint: true 傳遞至產生物件的方法時才會存在。表示自 POSIX Epoch 以來,存取此檔案的最後時間戳記,以奈秒為單位。

stats.mtimeNs#

僅在將 bigint: true 傳遞至產生物件的方法時才會存在。表示自 POSIX Epoch 以來,修改此檔案的最後時間戳記,以奈秒為單位。

stats.ctimeNs#

僅在將 bigint: true 傳遞至產生物件的方法時才會存在。表示自 POSIX Epoch 以來,變更檔案狀態的最後時間戳記,以奈秒為單位。

stats.birthtimeNs#

僅在將 bigint: true 傳遞至產生物件的方法時才會存在。表示建立此檔案的時間戳記,以奈秒為單位。

stats.atime#

指示上次存取此檔案的時間戳記。

stats.mtime#

指示上次修改此檔案的時間戳記。

stats.ctime#

指示上次變更檔案狀態的時間戳記。

stats.birthtime#

指示此檔案的建立時間戳記。

統計時間值#

atimeMsmtimeMsctimeMsbirthtimeMs 屬性為數值,以毫秒為單位儲存對應時間。其精確度取決於平台。當將 bigint: true 傳遞給產生物件的方法時,這些屬性會是 bigint,否則會是 數字

atimeNsmtimeNsctimeNsbirthtimeNs 屬性為 bigint,以奈秒為單位儲存對應時間。只有在將 bigint: true 傳遞給產生物件的方法時,這些屬性才會存在。其精確度取決於平台。

atimemtimectimebirthtimeDate 物件,用來作為各種時間的替代表示法。Date 和數字值並未連接。指定新的數字值或變更 Date 值,不會反映在對應的替代表示法中。

統計物件中的時間具有下列語意

  • atime「存取時間」:上次存取檔案資料的時間。由 mknod(2)utimes(2)read(2) 系統呼叫變更。
  • mtime「修改時間」:檔案資料最後修改時間。由 mknod(2)utimes(2)write(2) 系統呼叫變更。
  • ctime「變更時間」:檔案狀態最後變更時間(inode 資料修改)。由 chmod(2)chown(2)link(2)mknod(2)rename(2)unlink(2)utimes(2)read(2)write(2) 系統呼叫變更。
  • birthtime「建立時間」:檔案建立時間。檔案建立時設定一次。在無法取得建立時間的檔案系統上,此欄位可能會改為儲存 ctime1970-01-01T00:00Z(即 Unix 紀元時間戳記 0)。這種情況下,此值可能會大於 atimemtime。在 Darwin 和其他 FreeBSD 變體上,如果使用 utimes(2) 系統呼叫將 atime 明確設定為早於目前的 birthtime,也會設定此值。

在 Node.js 0.12 之前,ctime 在 Windows 系統上會儲存 birthtime。從 0.12 開始,ctime 不再是「建立時間」,在 Unix 系統上也從未是「建立時間」。

類別:fs.StatFs#

提供已掛載檔案系統的資訊。

fs.statfs() 和其同步對應函式傳回的物件為此類型。如果傳遞給這些方法的 options 中的 biginttrue,數值會是 bigint,而不是 number

StatFs {
  type: 1397114950,
  bsize: 4096,
  blocks: 121938943,
  bfree: 61058895,
  bavail: 61058895,
  files: 999,
  ffree: 1000000
} 

bigint 版本

StatFs {
  type: 1397114950n,
  bsize: 4096n,
  blocks: 121938943n,
  bfree: 61058895n,
  bavail: 61058895n,
  files: 999n,
  ffree: 1000000n
} 
statfs.bavail#

未經授權的使用者可用的可用區塊。

statfs.bfree#

檔案系統中的可用區塊。

statfs.blocks#

檔案系統中的總資料區塊。

statfs.bsize#

最佳傳輸區塊大小。

statfs.ffree#

檔案系統中的可用檔案節點。

statfs.files#

檔案系統中的總檔案節點。

statfs.type#

檔案系統類型。

類別:fs.WriteStream#

使用 fs.createWriteStream() 函式建立 <fs.WriteStream> 的執行個體並傳回。

事件:'close'#

<fs.WriteStream> 的底層檔案描述符已關閉時發出。

事件:'open'#

<fs.WriteStream> 的檔案開啟時發出。

事件:'ready'#

<fs.WriteStream> 準備好使用時發出。

'open' 之後立即觸發。

writeStream.bytesWritten#

到目前為止寫入的位元組數。不包括仍排隊等候寫入的資料。

writeStream.close([callback])#

關閉 writeStream。選擇性地接受一個會在 writeStream 關閉後執行的回呼函式。

writeStream.path#

串流寫入檔案的路徑,如 fs.createWriteStream() 的第一個引數中所指定。如果 path 傳入的是字串,則 writeStream.path 會是字串。如果 path 傳入的是 <Buffer>,則 writeStream.path 會是 <Buffer>

writeStream.pending#

如果基礎檔案尚未開啟,則此屬性為 true,即在發出 'ready' 事件之前。

fs.constants#

傳回一個包含檔案系統操作中常用的常數的物件。

檔案系統常數#

下列常數由 fs.constantsfsPromises.constants 匯出。

並非每個常數都會在每個作業系統上提供;這對 Windows 來說特別重要,因為許多 POSIX 特定的定義並未提供。對於可攜式應用程式,建議在使用前檢查它們是否存在。

若要使用多個常數,請使用按位元 OR | 運算子。

範例

import { open, constants } from 'node:fs';

const {
  O_RDWR,
  O_CREAT,
  O_EXCL,
} = constants;

open('/path/to/my/file', O_RDWR | O_CREAT | O_EXCL, (err, fd) => {
  // ...
}); 
檔案存取常數#

下列常數用於傳遞給 fsPromises.access()fs.access()fs.accessSync()mode 參數。

常數 說明
F_OK 旗標,表示呼叫處理程序可見檔案。這對於判斷檔案是否存在很有用,但不會說明 rwx 權限。如果未指定模式,則為預設值。
R_OK 旗標,表示呼叫處理程序可以讀取檔案。
W_OK 旗標,表示呼叫處理程序可以寫入檔案。
X_OK 旗標,表示呼叫處理程序可以執行檔案。這對 Windows 沒有影響(會像 fs.constants.F_OK 一樣運作)。

這些定義在 Windows 上也可用。

檔案複製常數#

下列常數用於 fs.copyFile()

常數 說明
COPYFILE_EXCL 如果存在,當目的地路徑已存在時,複製作業會失敗並傳回錯誤。
COPYFILE_FICLONE 如果存在,複製作業會嘗試建立寫入時複製 reflink。如果底層平台不支援寫入時複製,則會使用備用複製機制。
COPYFILE_FICLONE_FORCE 如果存在,複製作業會嘗試建立寫入時複製 reflink。如果底層平台不支援寫入時複製,則作業會失敗並傳回錯誤。

這些定義在 Windows 上也可用。

檔案開啟常數#

下列常數是用於 fs.open() 的。

常數 說明
O_RDONLY 標示開啟檔案以唯讀存取的旗標。
O_WRONLY 標示開啟檔案以唯寫存取的旗標。
O_RDWR 標示開啟檔案以讀寫存取的旗標。
O_CREAT 標示如果檔案不存在則建立檔案的旗標。
O_EXCL 標示如果設定 O_CREAT 旗標且檔案已存在,則開啟檔案應失敗的旗標。
O_NOCTTY 標示如果路徑識別終端裝置,開啟路徑不應導致該終端成為該程序的控制終端(如果該程序尚未有控制終端)的旗標。
O_TRUNC 標示如果檔案存在且為一般檔案,且檔案已成功開啟以寫入存取,則其長度應截斷為零的旗標。
O_APPEND 標示資料將附加到檔案結尾的旗標。
O_DIRECTORY 標示如果路徑不是目錄,則開啟應失敗的旗標。
O_NOATIME 標示對檔案系統的讀取存取不再會導致與檔案相關聯的 atime 資訊更新的旗標。此旗標僅在 Linux 作業系統上可用。
O_NOFOLLOW 標示如果路徑是符號連結,則開啟應失敗的旗標。
O_SYNC 標示檔案已開啟以同步 I/O,寫入作業會等待檔案完整性。
O_DSYNC 標示檔案已開啟以同步 I/O,寫入作業會等待資料完整性。
O_SYMLINK 標示開啟符號連結本身,而不是它指向的資源的旗標。
O_DIRECT 設定時,將嘗試將檔案 I/O 的快取效應降至最低。
O_NONBLOCK 旗標,指示在可能的情況下以非封鎖模式開啟檔案。
UV_FS_O_FILEMAP 設定時,將使用記憶體檔案對應來存取檔案。此旗標僅在 Windows 作業系統中可用。在其他作業系統中,此旗標將被忽略。

在 Windows 中,僅有 O_APPENDO_CREATO_EXCLO_RDONLYO_RDWRO_TRUNCO_WRONLYUV_FS_O_FILEMAP 可用。

檔案類型常數#

以下常數用於 <fs.Stats> 物件的 mode 屬性,以判斷檔案類型。

常數 說明
S_IFMT 用於萃取檔案類型代碼的位元遮罩。
S_IFREG 一般檔案的檔案類型常數。
S_IFDIR 目錄的檔案類型常數。
S_IFCHR 字元導向裝置檔案的檔案類型常數。
S_IFBLK 區塊導向裝置檔案的檔案類型常數。
S_IFIFO FIFO/管道的檔案類型常數。
S_IFLNK 符號連結的檔案類型常數。
S_IFSOCK Socket 的檔案類型常數。

在 Windows 中,僅有 S_IFCHRS_IFDIRS_IFLNKS_IFMTS_IFREG 可用。

檔案模式常數#

以下常數用於 <fs.Stats> 物件的 mode 屬性,以判斷檔案的存取權限。

常數 說明
S_IRWXU 檔案模式表示可由擁有者讀取、寫入和執行。
S_IRUSR 檔案模式表示可由擁有者讀取。
S_IWUSR 檔案模式表示可由擁有者寫入。
S_IXUSR 檔案模式表示可由擁有者執行。
S_IRWXG 檔案模式表示可由群組讀取、寫入和執行。
S_IRGRP 檔案模式表示可由群組讀取。
S_IWGRP 檔案模式表示可由群組寫入。
S_IXGRP 檔案模式表示可由群組執行。
S_IRWXO 檔案模式表示可由其他人讀取、寫入和執行。
S_IROTH 檔案模式表示可由其他人讀取。
S_IWOTH 檔案模式表示可由其他人寫入。
S_IXOTH 檔案模式表示可由其他人執行。

在 Windows 上,只有 S_IRUSRS_IWUSR 可用。

註解#

回呼和基於 Promise 的操作順序#

由於它們是由底層執行緒池非同步執行的,因此在使用回呼或基於 Promise 的方法時,沒有保證的順序。

例如,以下內容容易出錯,因為 fs.stat() 操作可能在 fs.rename() 操作之前完成

const fs = require('node:fs');

fs.rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  console.log('renamed complete');
});
fs.stat('/tmp/world', (err, stats) => {
  if (err) throw err;
  console.log(`stats: ${JSON.stringify(stats)}`);
}); 

正確的順序執行操作很重要,在呼叫另一個操作之前,請等待一個操作的結果

import { rename, stat } from 'node:fs/promises';

const oldPath = '/tmp/hello';
const newPath = '/tmp/world';

try {
  await rename(oldPath, newPath);
  const stats = await stat(newPath);
  console.log(`stats: ${JSON.stringify(stats)}`);
} catch (error) {
  console.error('there was an error:', error.message);
}const { rename, stat } = require('node:fs/promises');

(async function(oldPath, newPath) {
  try {
    await rename(oldPath, newPath);
    const stats = await stat(newPath);
    console.log(`stats: ${JSON.stringify(stats)}`);
  } catch (error) {
    console.error('there was an error:', error.message);
  }
})('/tmp/hello', '/tmp/world');

或者,在使用回呼 API 時,將 fs.stat() 呼叫移至 fs.rename() 操作的回呼中

import { rename, stat } from 'node:fs';

rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  stat('/tmp/world', (err, stats) => {
    if (err) throw err;
    console.log(`stats: ${JSON.stringify(stats)}`);
  });
});const { rename, stat } = require('node:fs/promises');

rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  stat('/tmp/world', (err, stats) => {
    if (err) throw err;
    console.log(`stats: ${JSON.stringify(stats)}`);
  });
});

檔案路徑#

大多數 fs 操作接受可以指定為字串、<Buffer> 或使用 file: 協定的 <URL> 物件形式的檔案路徑。

字串路徑#

字串路徑會被解釋為 UTF-8 字元序列,用以識別絕對或相對檔案名稱。相對路徑會根據呼叫 `process.cwd()` 所決定的目前工作目錄來解析。

在 POSIX 上使用絕對路徑的範例

import { open } from 'node:fs/promises';

let fd;
try {
  fd = await open('/open/some/file.txt', 'r');
  // Do something with the file
} finally {
  await fd?.close();
} 

在 POSIX 上使用相對路徑的範例(相對於 `process.cwd()`)

import { open } from 'node:fs/promises';

let fd;
try {
  fd = await open('file.txt', 'r');
  // Do something with the file
} finally {
  await fd?.close();
} 
檔案 URL 路徑#

對於大多數 `node:fs` 模組函式,`path` 或 `filename` 參數可以使用 `file:` 協定的 <URL> 物件傳遞。

import { readFileSync } from 'node:fs';

readFileSync(new URL('file:///tmp/hello')); 

file: URL 永遠是絕對路徑。

特定於平台的考量#

在 Windows 上,具有主機名稱的 file: <URL> 會轉換為 UNC 路徑,而具有磁碟機代號的 file: <URL> 會轉換為本機絕對路徑。沒有主機名稱和磁碟機代號的 file: <URL> 會導致錯誤

import { readFileSync } from 'node:fs';
// On Windows :

// - WHATWG file URLs with hostname convert to UNC path
// file://hostname/p/a/t/h/file => \\hostname\p\a\t\h\file
readFileSync(new URL('file://hostname/p/a/t/h/file'));

// - WHATWG file URLs with drive letters convert to absolute path
// file:///C:/tmp/hello => C:\tmp\hello
readFileSync(new URL('file:///C:/tmp/hello'));

// - WHATWG file URLs without hostname must have a drive letters
readFileSync(new URL('file:///notdriveletter/p/a/t/h/file'));
readFileSync(new URL('file:///c/p/a/t/h/file'));
// TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute 

具有磁碟機代號的 file: <URL> 必須在磁碟機代號後使用 `:` 作為分隔符號。使用其他分隔符號會導致錯誤。

在其他所有平台上,具有主機名稱的 file: <URL> 不受支援,並且會導致錯誤

import { readFileSync } from 'node:fs';
// On other platforms:

// - WHATWG file URLs with hostname are unsupported
// file://hostname/p/a/t/h/file => throw!
readFileSync(new URL('file://hostname/p/a/t/h/file'));
// TypeError [ERR_INVALID_FILE_URL_PATH]: must be absolute

// - WHATWG file URLs convert to absolute path
// file:///tmp/hello => /tmp/hello
readFileSync(new URL('file:///tmp/hello')); 

具有編碼斜線字元的 file: <URL> 會在所有平台上導致錯誤

import { readFileSync } from 'node:fs';

// On Windows
readFileSync(new URL('file:///C:/p/a/t/h/%2F'));
readFileSync(new URL('file:///C:/p/a/t/h/%2f'));
/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded
\ or / characters */

// On POSIX
readFileSync(new URL('file:///p/a/t/h/%2F'));
readFileSync(new URL('file:///p/a/t/h/%2f'));
/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded
/ characters */ 

在 Windows 上,具有編碼反斜線的 file: <URL> 會導致錯誤

import { readFileSync } from 'node:fs';

// On Windows
readFileSync(new URL('file:///C:/path/%5C'));
readFileSync(new URL('file:///C:/path/%5c'));
/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded
\ or / characters */ 
Buffer 路徑#

使用 <Buffer> 指定的路徑主要在某些將檔案路徑視為不透明位元組序列的 POSIX 作業系統上很有用。在這些系統上,單一檔案路徑有可能包含使用多種字元編碼的子序列。與字串路徑一樣,<Buffer> 路徑可能是相對或絕對的

在 POSIX 上使用絕對路徑的範例

import { open } from 'node:fs/promises';
import { Buffer } from 'node:buffer';

let fd;
try {
  fd = await open(Buffer.from('/open/some/file.txt'), 'r');
  // Do something with the file
} finally {
  await fd?.close();
} 
Windows 上的每個磁碟工作目錄#

在 Windows 上,Node.js 遵循每個磁碟工作目錄的概念。當使用沒有反斜線的磁碟路徑時,可以觀察到此行為。例如,fs.readdirSync('C:\\') 可能會傳回與 fs.readdirSync('C:') 不同的結果。如需更多資訊,請參閱 此 MSDN 頁面

檔案描述符#

在 POSIX 系統上,對於每個程序,核心會維護一個目前開啟檔案和資源的表格。每個開啟的檔案會指派一個稱為檔案描述符的簡單數字識別碼。在系統層級,所有檔案系統作業都會使用這些檔案描述符來識別和追蹤每個特定檔案。Windows 系統使用不同但概念上類似的機制來追蹤資源。為了簡化使用者操作,Node.js 會抽象化作業系統之間的差異,並指派所有開啟檔案一個數字檔案描述符。

基於回呼的 fs.open() 和同步的 fs.openSync() 方法會開啟一個檔案並配置一個新的檔案描述符。配置後,檔案描述符可以用來從檔案讀取資料、寫入資料或要求檔案資訊。

作業系統會限制在任何特定時間可以開啟的檔案描述符數量,因此在作業完成時關閉描述符非常重要。如果沒有這麼做,將會導致記憶體外洩,最後會導致應用程式當機。

import { open, close, fstat } from 'node:fs';

function closeFd(fd) {
  close(fd, (err) => {
    if (err) throw err;
  });
}

open('/open/some/file.txt', 'r', (err, fd) => {
  if (err) throw err;
  try {
    fstat(fd, (err, stat) => {
      if (err) {
        closeFd(fd);
        throw err;
      }

      // use stat

      closeFd(fd);
    });
  } catch (err) {
    closeFd(fd);
    throw err;
  }
}); 

基於承諾的 API 會使用 <FileHandle> 物件取代數字檔案描述符。這些物件由系統更妥善地管理,以確保資源不會外洩。然而,在作業完成時,仍然需要關閉這些物件。

import { open } from 'node:fs/promises';

let file;
try {
  file = await open('/open/some/file.txt', 'r');
  const stat = await file.stat();
  // use stat
} finally {
  await file.close();
} 

執行緒池使用#

所有回呼和基於承諾的檔案系統 API(除了 fs.FSWatcher())都使用 libuv 的執行緒池。這可能會對某些應用程式造成令人驚訝且負面的效能影響。請參閱 UV_THREADPOOL_SIZE 文件以取得更多資訊。

檔案系統旗標#

只要 flag 選項採用字串,就會提供下列旗標。

  • 'a':開啟檔案以附加。如果檔案不存在,就會建立檔案。

  • 'ax':類似於 'a',但如果路徑存在,就會失敗。

  • 'a+':開啟檔案以讀取和附加。如果檔案不存在,就會建立檔案。

  • 'ax+':類似於 'a+',但如果路徑存在,就會失敗。

  • 'as':以同步模式開啟檔案以附加。如果檔案不存在,就會建立檔案。

  • 'as+':以同步模式開啟檔案以讀取和附加。如果檔案不存在,就會建立檔案。

  • 'r':開啟檔案以讀取。如果檔案不存在,就會發生例外狀況。

  • 'rs':以同步模式開啟檔案以讀取。如果檔案不存在,就會發生例外狀況。

  • 'r+':開啟檔案以讀取和寫入。如果檔案不存在,就會發生例外狀況。

  • 'rs+':以同步模式開啟檔案以讀取和寫入。指示作業系統略過本機檔案系統快取。

    這主要適用於開啟 NFS 掛載上的檔案,因為它允許略過可能過期的本機快取。它對 I/O 效能有非常實際的影響,因此除非有需要,否則不建議使用此旗標。

    這不會將 fs.open()fsPromises.open() 轉換為同步封鎖呼叫。如果需要同步操作,應使用類似 fs.openSync() 的方法。

  • 'w':開啟檔案以寫入。檔案會建立(如果不存在)或截斷(如果存在)。

  • 'wx':類似於 'w',但如果路徑存在,則會失敗。

  • 'w+':開啟檔案進行讀取和寫入。檔案會建立(如果不存在)或截斷(如果存在)。

  • 'wx+':類似於 'w+',但如果路徑存在,則會失敗。

flag 也可以是數字,如 open(2) 所記載;常用的常數可從 fs.constants 取得。在 Windows 上,旗標會轉換為適用的等效旗標,例如 O_WRONLY 轉換為 FILE_GENERIC_WRITE,或 O_EXCL|O_CREAT 轉換為 CREATE_NEW,如 CreateFileW 所接受。

獨佔旗標 'x'open(2) 中的 O_EXCL 旗標)會導致操作在路徑已存在時傳回錯誤。在 POSIX 上,如果路徑是符號連結,使用 O_EXCL 會傳回錯誤,即使連結指向不存在的路徑。獨佔旗標可能無法與網路檔案系統一起使用。

在 Linux 上,當檔案以附加模式開啟時,位置寫入無法運作。核心會忽略位置參數,並始終將資料附加到檔案結尾。

修改檔案而非取代檔案可能需要將 flag 選項設定為 'r+',而不是預設的 'w'

某些旗標的行為取決於平台。因此,在 macOS 和 Linux 上使用 'a+' 旗標開啟目錄,如同以下範例,會傳回錯誤。相反地,在 Windows 和 FreeBSD 上,會傳回檔案描述符或 FileHandle

// macOS and Linux
fs.open('<directory>', 'a+', (err, fd) => {
  // => [Error: EISDIR: illegal operation on a directory, open <directory>]
});

// Windows and FreeBSD
fs.open('<directory>', 'a+', (err, fd) => {
  // => null, <fd>
}); 

在 Windows 上,使用 'w' 旗標開啟現有的隱藏檔案(透過 fs.open()fs.writeFile()fsPromises.open())會失敗,並傳回 EPERM。現有的隱藏檔案可以使用 'r+' 旗標開啟進行寫入。

呼叫 fs.ftruncate()filehandle.truncate() 可用於重設檔案內容。