檔案系統#

穩定性:2 - 穩定

原始碼: lib/fs.js

node:fs 模組使得能夠以一種模仿標準 POSIX 函式的方式與檔案系統進行互動。

要使用基於 Promise 的 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');

所有檔案系統操作都有同步、回撥和基於 Promise 的形式,並且可以使用 CommonJS 語法和 ES6 模組(ESM)進行訪問。

Promise 示例#

基於 Promise 的操作返回一個 Promise,該 Promise 在非同步操作完成時被兌現。

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 的基於回撥的版本比使用 Promise 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
}

Promises API#

fs/promises API 提供了返回 Promise 的非同步檔案系統方法。

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

類: FileHandle#

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

<FileHandle> 物件的例項由 fsPromises.open() 方法建立。

所有的 <FileHandle> 物件都是 <EventEmitter>s。

如果一個 <FileHandle> 沒有使用 filehandle.close() 方法關閉,它將嘗試自動關閉檔案描述符併發出一個程序警告,以幫助防止記憶體洩漏。請不要依賴此行為,因為它可能不可靠,檔案可能不會被關閉。相反,請始終顯式關閉 <FileHandle>s。Node.js 將來可能會更改此行為。

事件: 'close'#

<FileHandle> 已被關閉並且不能再使用時,會發出 'close' 事件。

filehandle.appendFile(data[, options])#

filehandle.writeFile() 的別名。

在操作檔案控制代碼時,模式不能從使用 fsPromises.open() 設定的模式更改。因此,這等同於 filehandle.writeFile()

filehandle.chmod(mode)#
  • mode <integer> 檔案模式位掩碼。
  • 返回: <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])#

options 可以包含 startend 值,以從檔案中讀取一個位元組範圍,而不是整個檔案。startend 都是包含性的,從 0 開始計數,允許的值在 [0, Number.MAX_SAFE_INTEGER] 範圍內。如果省略或為 undefinedfilehandle.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])#

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

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

預設情況下,流在被銷燬後會發出 'close' 事件。將 emitClose 選項設定為 false 以更改此行為。

filehandle.datasync()#
  • 返回: <Promise> 成功時兌現為 undefined

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

filehandle.sync 不同,此方法不重新整理修改後的元資料。

filehandle.fd#
filehandle.read(buffer, offset, length, position)#
  • buffer <Buffer> | <TypedArray> | <DataView> 將被填充讀取的檔案資料的緩衝區。
  • offset <integer> 緩衝區中開始填充的位置。預設: 0
  • length <integer> 要讀取的位元組數。預設: buffer.byteLength - offset
  • position <integer> | <bigint> | <null> 從檔案中開始讀取資料的位置。如果為 null-1,將從當前檔案位置讀取資料,並且該位置將被更新。如果 position 是一個非負整數,則當前檔案位置將保持不變。預設: null
  • 返回: <Promise> 成功時兌現,返回一個包含兩個屬性的物件

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

如果檔案沒有被併發修改,當讀取的位元組數為零時,即到達檔案末尾。

filehandle.read([options])#
  • options <Object>
    • buffer <Buffer> | <TypedArray> | <DataView> 將被填充讀取的檔案資料的緩衝區。預設: Buffer.alloc(16384)
    • offset <integer> 緩衝區中開始填充的位置。預設: 0
    • length <integer> 要讀取的位元組數。預設: buffer.byteLength - offset
    • position <integer> | <bigint> | <null> 從檔案中開始讀取資料的位置。如果為 null-1,將從當前檔案位置讀取資料,並且該位置將被更新。如果 position 是一個非負整數,則當前檔案位置將保持不變。預設: null
  • 返回: <Promise> 成功時兌現,返回一個包含兩個屬性的物件

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

如果檔案沒有被併發修改,當讀取的位元組數為零時,即到達檔案末尾。

filehandle.read(buffer[, options])#
  • buffer <Buffer> | <TypedArray> | <DataView> 將被填充讀取的檔案資料的緩衝區。
  • options <Object>
    • offset <integer> 緩衝區中開始填充的位置。預設: 0
    • length <integer> 要讀取的位元組數。預設: buffer.byteLength - offset
    • position <integer> | <bigint> | <null> 從檔案中開始讀取資料的位置。如果為 null-1,將從當前檔案位置讀取資料,並且該位置將被更新。如果 position 是一個非負整數,則當前檔案位置將保持不變。預設: null
  • 返回: <Promise> 成功時兌現,返回一個包含兩個屬性的物件

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

如果檔案沒有被併發修改,當讀取的位元組數為零時,即到達檔案末尾。

filehandle.readableWebStream([options])#

返回一個面向位元組的 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() 方法,除非 autoClose 選項設定為 true

filehandle.readFile(options)#
  • options <Object> | <string>
  • 返回: <Promise> 成功讀取後兌現,其值為檔案的內容。如果未指定編碼(使用 options.encoding),則資料作為 <Buffer> 物件返回。否則,資料將是字串。

非同步讀取檔案的全部內容。

如果 options 是一個字串,則它指定了 encoding

<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> 引用的物件的檔案系統時間戳,成功後兌現不帶任何引數的 Promise。

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 寫入檔案。

該 Promise 將被兌現,並返回一個包含兩個屬性的物件

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

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

filehandle.write(buffer[, options])#

buffer 寫入檔案。

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

filehandle.write(string[, position[, encoding]])#
  • string <string>
  • position <integer> | <null> 從檔案開頭開始寫入 string 中資料的偏移量。如果 position 不是 number,則資料將寫入當前位置。有關更多詳細資訊,請參閱 POSIX pwrite(2) 文件。預設: null
  • encoding <string> 預期的字串編碼。預設: 'utf8'
  • 返回:<Promise>

string 寫入檔案。如果 string 不是字串,則 Promise 會因錯誤而拒絕。

該 Promise 將被兌現,並返回一個包含兩個屬性的物件

  • bytesWritten <integer> 寫入的位元組數
  • buffer <string> 對寫入的 string 的引用。

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

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

filehandle.writeFile(data, options)#

非同步地將資料寫入檔案,如果檔案已存在則替換該檔案。data 可以是字串、緩衝區、<AsyncIterable><Iterable> 物件。成功後,Promise 將兌現為不帶任何引數的值。

如果 options 是一個字串,則它指定了 encoding

<FileHandle> 必須支援寫入。

在未等待 Promise 兌現(或拒絕)的情況下,在同一檔案上多次使用 filehandle.writeFile() 是不安全的。

如果在檔案控制代碼上進行了一次或多次 filehandle.write() 呼叫,然後進行 filehandle.writeFile() 呼叫,資料將從當前位置寫入到檔案末尾。它並不總是從檔案開頭寫入。

filehandle.writev(buffers[, position])#

<ArrayBufferView>s 陣列寫入檔案。

該 Promise 將被兌現,並返回一個包含兩個屬性的物件

在未等待 Promise 兌現(或拒絕)的情況下,在同一檔案上多次呼叫 writev() 是不安全的。

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

filehandle[Symbol.asyncDispose]()#

呼叫 filehandle.close() 並返回一個 Promise,該 Promise 在檔案控制代碼關閉時兌現。

fsPromises.access(path[, mode])#

測試使用者對 path 指定的檔案或目錄的許可權。mode 引數是一個可選的整數,指定要執行的可訪問性檢查。mode 應該是值 fs.constants.F_OK 或由 fs.constants.R_OKfs.constants.W_OKfs.constants.X_OK 中任意一個或多個的按位或組成的掩碼(例如 fs.constants.W_OK | fs.constants.R_OK)。請檢查檔案訪問常量以瞭解 mode 的可能值。

如果可訪問性檢查成功,Promise 將兌現為無值。如果任何可訪問性檢查失敗,Promise 將被拒絕並帶有一個 <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.open() 之前使用 fsPromises.access() 檢查檔案的可訪問性。這樣做會引入競態條件,因為其他程序可能會在兩次呼叫之間更改檔案的狀態。相反,使用者程式碼應該直接開啟/讀取/寫入檔案,並處理檔案不可訪問時引發的錯誤。

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

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

如果 options 是一個字串,則它指定了 encoding

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> 指定複製操作行為的可選修飾符。可以透過兩個或多個值的按位或來建立一個掩碼(例如 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])#

  • src <string> | <URL> 要複製的源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 解引用符號連結。預設: false
    • errorOnExist <boolean>forcefalse 且目標存在時,丟擲錯誤。預設: false
    • filter <Function> 用於過濾複製的檔案/目錄的函式。返回 true 以複製該項,返回 false 以忽略它。當忽略一個目錄時,其所有內容也將被跳過。也可以返回一個解析為 truefalsePromise預設: undefined
      • src <string> 要複製的源路徑。
      • dest <string> 要複製到的目標路徑。
      • 返回: <boolean> | <Promise> 一個可以強制轉換為 boolean 的值或一個兌現為此類值的 Promise
    • force <boolean> 覆蓋現有的檔案或目錄。如果將此設定為 false 且目標存在,複製操作將忽略錯誤。使用 errorOnExist 選項來更改此行為。預設: true
    • mode <integer> 複製操作的修飾符。預設: 0。參見 fsPromises.copyFile()mode 標誌。
    • preserveTimestamps <boolean> 當為 true 時,將保留 src 的時間戳。預設: false
    • recursive <boolean> 遞迴複製目錄 預設: false
    • verbatimSymlinks <boolean> 當為 true 時,將跳過符號連結的路徑解析。預設: false
  • 返回: <Promise> 成功時兌現為 undefined

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

將目錄複製到另一個目錄時,不支援萬用字元,行為類似於 cp dir1/ dir2/

fsPromises.glob(pattern[, options])#

  • pattern <string> | <string[]>
  • options <Object>
    • cwd <string> | <URL> 當前工作目錄。預設: process.cwd()
    • exclude <Function> | <string[]> 用於過濾檔案/目錄的函式或要排除的 glob 模式列表。如果提供函式,返回 true 表示排除該項,返回 false 表示包含。預設: undefined。如果提供字串陣列,則每個字串都應為指定要排除路徑的 glob 模式。注意:不支援否定模式(例如 `!foo.js`)。
    • withFileTypes <boolean> 如果 glob 應返回 Dirents 形式的路徑,則為 true,否則為 false預設: false
  • 返回: <AsyncIterator> 一個 AsyncIterator,它產生與模式匹配的檔案路徑。
import { glob } from 'node:fs/promises';

for await (const entry of glob('**/*.js'))
  console.log(entry);const { glob } = require('node:fs/promises');

(async () => {
  for await (const entry of glob('**/*.js'))
    console.log(entry);
})();

fsPromises.lchmod(path, mode)#

穩定性: 0 - 廢棄

更改符號連結的許可權。

此方法僅在 macOS 上實現。

fsPromises.lchown(path, uid, gid)#

更改符號連結的所有權。

fsPromises.lutimes(path, atime, mtime)#

以與 fsPromises.utimes() 相同的方式更改檔案的訪問和修改時間,不同之處在於如果路徑引用一個符號連結,則該連結不會被解引用:而是更改符號連結本身的時間戳。

fsPromises.link(existingPath, newPath)#

existingPath 建立到 newPath 的新連結。有關更多詳細資訊,請參閱 POSIX link(2) 文件。

fsPromises.lstat(path[, options])#

等同於 fsPromises.stat(),除非 path 引用一個符號連結,在這種情況下,統計的是連結本身,而不是它引用的檔案。有關更多詳細資訊,請參閱 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.mkdtempDisposable(prefix[, options])#

生成的 Promise 持有一個非同步可處置物件,其 path 屬性儲存了建立的目錄路徑。當該物件被處置時,如果目錄仍然存在,它及其內容將被非同步刪除。如果目錄無法刪除,處置將丟擲錯誤。該物件有一個非同步的 remove() 方法,它將執行相同的任務。

此函式和結果物件上的處置函式都是非同步的,因此應與 await + await using 一起使用,如 await using dir = await fsPromises.mkdtempDisposable('prefix')

有關詳細資訊,請參閱 fsPromises.mkdtemp() 的文件。

可選的 options 引數可以是一個指定編碼的字串,或一個帶有 encoding 屬性的物件,指定要使用的字元編碼。

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 <string> | <Object>
    • encoding <string> 預設值: 'utf8'
    • withFileTypes <boolean> 預設: false
    • recursive <boolean> 如果為 true,則遞迴讀取目錄的內容。在遞迴模式下,它將列出所有檔案、子檔案和目錄。預設: false
  • 返回: <Promise> 兌現一個包含目錄中檔名陣列的 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 上,Promise 將被拒絕並帶有一個錯誤。在 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。如果請求被中止,返回的 Promise 將被拒絕並帶有一個 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) 文件。成功後,Promise 將兌現 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 時,procfs 檔案系統必須掛載在 /proc 上才能使此函式正常工作。Glibc 沒有此限制。

fsPromises.rename(oldPath, newPath)#

oldPath 重新命名為 newPath

fsPromises.rmdir(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object> 目前沒有公開的選項。以前曾有用於 recursivemaxBusyTriesemfileWait 的選項,但它們已被棄用和移除。為了向後相容,仍然接受 options 引數,但不會使用它。
  • 返回: <Promise> 成功時兌現為 undefined

移除由 path 標識的目錄。

在檔案(而不是目錄)上使用 fsPromises.rmdir() 會導致在 Windows 上 promise 被拒絕並返回 ENOENT 錯誤,在 POSIX 上則返回 ENOTDIR 錯誤。

要獲得類似於 Unix 命令 rm -rf 的行為,請使用 fsPromises.rm() 並設定選項 { recursive: true, force: true }

fsPromises.rm(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • force <boolean> 當為 true 時,如果 path 不存在,異常將被忽略。預設值:false
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 將在每次嘗試時以 retryDelay 毫秒的線性退避等待時間重試操作。此選項表示重試次數。如果 recursive 選項不為 true,則此選項將被忽略。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴目錄刪除。在遞迴模式下,操作失敗時會重試。預設值:false
    • retryDelay <integer> 兩次重試之間等待的時間(以毫秒為單位)。如果 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 引數為 null,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 <string> | <Buffer> | <URL>
  • options <string> | <Object>
    • persistent <boolean> 指示只要檔案被監視,程序是否應繼續執行。預設值:true
    • recursive <boolean> 指示是否應監視所有子目錄,或僅監視當前目錄。這在指定目錄時適用,並且僅在受支援的平臺上有效(請參閱注意事項)。預設值:false
    • encoding <string> 指定用於傳遞給監聽器的檔名的字元編碼。預設值:'utf8'
    • signal <AbortSignal> 一個 <AbortSignal>,用於發出監視器應停止的訊號。
    • maxQueue <number> 指定在返回的 <AsyncIterator> 的迭代之間要排隊的事件數量。預設值:2048
    • overflow <string> 當有比 maxQueue 允許的更多事件要排隊時,可以是 'ignore''throw''ignore' 表示溢位事件被丟棄併發出警告,而 'throw' 表示丟擲異常。預設值:'ignore'
  • 返回:<AsyncIterator>,其物件具有以下屬性

返回一個非同步迭代器,用於監視 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 是緩衝區,則忽略 encoding 選項。

如果 options 是一個字串,則它指定了編碼。

mode 選項僅影響新建立的檔案。有關更多詳細資訊,請參見 fs.open()

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

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

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 中任意一個或多個的按位或組成的掩碼(例如 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 引數是使用以下常量的邏輯或運算建立的數字位掩碼

常量八進位制描述
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 的值都可能導致平臺特定的行為,這些行為不支援一致地工作。因此,像 S_ISVTXS_ISGIDS_ISUID 這樣的常量沒有在 fs.constants 中公開。

注意事項:在 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)#

  • src <string> | <URL> 要複製的源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 解引用符號連結。預設: false
    • errorOnExist <boolean>forcefalse 且目標存在時,丟擲錯誤。預設: false
    • filter <Function> 用於過濾複製的檔案/目錄的函式。返回 true 以複製該項,返回 false 以忽略它。當忽略一個目錄時,其所有內容也將被跳過。也可以返回一個解析為 truefalsePromise預設: undefined
      • src <string> 要複製的源路徑。
      • dest <string> 要複製到的目標路徑。
      • 返回: <boolean> | <Promise> 一個可以強制轉換為 boolean 的值或一個兌現為此類值的 Promise
    • force <boolean> 覆蓋現有的檔案或目錄。如果將此設定為 false 且目標存在,複製操作將忽略錯誤。使用 errorOnExist 選項來更改此行為。預設: true
    • mode <integer> 複製操作的修飾符。預設值:0。請參閱 fs.copyFile()mode 標誌。
    • preserveTimestamps <boolean> 當為 true 時,將保留 src 的時間戳。預設: false
    • recursive <boolean> 遞迴複製目錄 預設: false
    • verbatimSymlinks <boolean> 當為 true 時,將跳過符號連結的路徑解析。預設: false
  • callback <Function>

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

將目錄複製到另一個目錄時,不支援萬用字元,行為類似於 cp dir1/ dir2/

fs.createReadStream(path[, options])#

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

如果指定了 fdReadStream 將忽略 path 引數,並使用指定的檔案描述符。這意味著不會發出 'open' 事件。fd 應該是阻塞的;非阻塞的 fd 應該傳遞給 <net.Socket>

如果 fd 指向一個只支援阻塞讀取的字元裝置(如鍵盤或音效卡),讀取操作在有資料可用之前不會完成。這可能會阻止程序退出和流自然關閉。

預設情況下,流在被銷燬後會發出 'close' 事件。將 emitClose 選項設定為 false 以更改此行為。

透過提供 fs 選項,可以覆蓋 openreadclose 對應的 fs 實現。當提供 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> 接受的任何一種。

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

預設情況下,流在被銷燬後會發出 'close' 事件。將 emitClose 選項設定為 false 以更改此行為。

透過提供 fs 選項,可以覆蓋 openwritewritevclose 對應的 fs 實現。覆蓋 write() 而不覆蓋 writev() 會降低效能,因為一些最佳化 (_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()

透過檢查檔案系統來測試給定 path 處的元素是否存在。然後用 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() 的原因之一。

如果 path 是一個符號連結,它會被跟隨。因此,如果 path 存在但指向一個不存在的元素,回撥函式將接收到值 false

不建議在呼叫 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.glob(pattern[, options], callback)#

  • pattern <string> | <string[]>

  • options <Object>

    • cwd <string> | <URL> 當前工作目錄。預設: process.cwd()
    • exclude <Function> | <string[]> 用於過濾檔案/目錄的函式,或要排除的 glob 模式列表。如果提供函式,返回 true 以排除專案,返回 false 以包含專案。預設值:undefined
    • withFileTypes <boolean> 如果 glob 應返回 Dirents 形式的路徑,則為 true,否則為 false預設: false
  • callback <Function>

  • 檢索與指定模式匹配的檔案。

import { glob } from 'node:fs';

glob('**/*.js', (err, matches) => {
  if (err) throw err;
  console.log(matches);
});const { glob } = require('node:fs');

glob('**/*.js', (err, matches) => {
  if (err) throw err;
  console.log(matches);
});

fs.lchmod(path, mode, callback)#

穩定性: 0 - 廢棄

更改符號連結的許可權。除了一個可能的異常外,沒有其他引數會傳遞給完成回撥函式。

此方法僅在 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)#

建立從 existingPathnewPath 的新連結。有關更多詳細資訊,請參閱 POSIX link(2) 文件。除了一個可能的異常外,沒有其他引數會傳遞給完成回撥函式。

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

檢索路徑所引用的符號連結的 <fs.Stats>。回撥函式接收兩個引數 (err, stats),其中 stats 是一個 <fs.Stats> 物件。lstat()stat() 相同,不同之處在於如果 path 是一個符號連結,那麼會獲取連結本身的狀態,而不是它所引用的檔案。

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

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

非同步地建立目錄。

回撥函式接收一個可能的異常,並且如果 recursivetrue,則接收第一個建立的目錄路徑 (err[, path])。當 recursivetrue 時,如果未建立目錄(例如,如果它之前已建立),path 仍然可以是 undefined

可選的 options 引數可以是一個指定 mode(許可權和粘滯位)的整數,或者是一個帶有 mode 屬性和 recursive 屬性(指示是否應建立父目錄)的物件。當 path 是一個已存在的目錄時,只有在 recursive 為 false 時呼叫 fs.mkdir() 才會導致錯誤。如果 recursive 為 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(prefix[, options], callback)#

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

生成六個隨機字元附加在必需的 prefix 後面,以建立一個唯一的臨時目錄。由於平臺不一致,請避免在 prefix 中使用尾隨的 X 字元。某些平臺,特別是 BSD,可以返回超過六個隨機字元,並用隨機字元替換 prefix 中的尾隨 X 字元。

建立的目錄路徑作為字串傳遞給回撥函式的第二個引數。

可選的 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])#

返回一個 <Blob>,其資料由給定檔案支援。

在建立 <Blob> 後不得修改檔案。任何修改都將導致讀取 <Blob> 資料時失敗並返回 DOMException 錯誤。在建立 Blob 時以及每次讀取之前,都會對檔案進行同步的 stat 操作,以檢測檔案資料在磁碟上是否已被修改。

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() 版本被呼叫,它將返回一個 promise,該 promise 解析為一個帶有 bytesReadbuffer 屬性的 Object

fs.read() 方法從檔案描述符 (fd) 指定的檔案中讀取資料。length 引數指示 Node.js 將嘗試從核心讀取的最大位元組數。然而,由於各種原因,實際讀取的位元組數 (bytesRead) 可能低於指定的 length

例如:

  • 如果檔案短於指定的 lengthbytesRead 將被設定為實際讀取的位元組數。
  • 如果在緩衝區被填滿之前檔案遇到 EOF(檔案結束),Node.js 將讀取所有可用位元組直到遇到 EOF,並且回撥中的 bytesRead 引數將指示實際讀取的位元組數,這可能小於指定的 length
  • 如果檔案位於慢速網路檔案系統上或在讀取期間遇到任何其他問題,bytesRead 可能低於指定的 length

因此,在使用 fs.read() 時,檢查 bytesRead 值以確定實際從檔案中讀取了多少位元組非常重要。根據您的應用程式邏輯,您可能需要處理 bytesRead 低於指定 length 的情況,例如,如果您需要最小數量的位元組,則可以將讀取呼叫包裝在迴圈中。

此行為類似於 POSIX preadv2 函式。

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 設定為 truefiles 陣列將包含 <fs.Dirent> 物件。

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

非同步讀取檔案的全部內容。

import { readFile } from 'node:fs';

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

回撥函式接收兩個引數 (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 被呼叫。

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)#

使用 readv()fd 指定的檔案中讀取資料,並寫入一個 ArrayBufferView 陣列。

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

回撥函式將接收三個引數:errbytesReadbuffersbytesRead 是從檔案中讀取的位元組數。

如果此方法作為其 util.promisify() 版本被呼叫,它將返回一個 promise,該 promise 解析為一個帶有 bytesReadbuffers 屬性的 Object

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

透過解析 ... 和符號連結來非同步計算規範路徑名。

規範路徑名不一定是唯一的。硬連結和繫結掛載可以透過許多路徑名暴露檔案系統實體。

此函式的行為類似於 realpath(3),但有一些例外

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

  2. 符號連結的最大數量是平臺無關的,通常比原生 realpath(3) 實現支援的數量要高(得多)。

回撥函式接收兩個引數 (err, resolvedPath)。可能會使用 process.cwd 來解析相對路徑。

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

可選的 options 引數可以是一個指定編碼的字串,或者是一個帶有 encoding 屬性的物件,用於指定傳遞給回撥函式的路徑所使用的字元編碼。如果 encoding 設定為 'buffer',返回的路徑將作為 <Buffer> 物件傳遞。

如果 path 解析為一個套接字或管道,該函式將返回該物件的系統相關名稱。

不存在的路徑會導致 ENOENT 錯誤。error.path 是絕對檔案路徑。

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

非同步 realpath(3)

回撥函式接收兩個引數 (err, resolvedPath)

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

可選的 options 引數可以是一個指定編碼的字串,或者是一個帶有 encoding 屬性的物件,用於指定傳遞給回撥函式的路徑所使用的字元編碼。如果 encoding 設定為 'buffer',返回的路徑將作為 <Buffer> 物件傳遞。

在 Linux 上,當 Node.js 連結到 musl libc 時,procfs 檔案系統必須掛載在 /proc 上才能使此函式正常工作。Glibc 沒有此限制。

fs.rename(oldPath, newPath, callback)#

非同步地將 oldPath 處的檔案重新命名為 newPath 提供的路徑名。如果 newPath 已存在,它將被覆蓋。如果 newPath 處存在一個目錄,則會引發錯誤。除了一個可能的異常外,沒有其他引數會傳遞給完成回撥函式。

另請參閱: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> 目前沒有公開的選項。以前曾有用於 recursivemaxBusyTriesemfileWait 的選項,但它們已被棄用和移除。為了向後相容,仍然接受 options 引數,但不會使用它。
  • callback <Function>

非同步 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 <boolean> 當為 true 時,如果 path 不存在,異常將被忽略。預設值:false
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 將在每次嘗試時以 retryDelay 毫秒的線性退避等待時間重試操作。此選項表示重試次數。如果 recursive 選項不為 true,則此選項將被忽略。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴刪除。在遞迴模式下,操作失敗時會重試。預設值:false
    • retryDelay <integer> 兩次重試之間等待的時間(以毫秒為單位)。如果 recursive 選項不為 true,則此選項將被忽略。預設值:100
  • callback <Function>

非同步地移除檔案和目錄(模仿標準的 POSIX rm 實用程式)。除了一個可能的異常外,沒有其他引數會傳遞給完成回撥函式。

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

非同步 stat(2)。回撥函式接收兩個引數 (err, stats),其中 stats 是一個 <fs.Stats> 物件。

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

fs.stat() 會跟隨符號連結。要檢視連結本身,請使用 fs.lstat()

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

要檢查檔案是否存在而不對其進行後續操作,建議使用 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 的已掛載檔案系統的資訊。回撥函式接收兩個引數 (err, stats),其中 stats 是一個 <fs.StatFs> 物件。

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

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

建立名為 path 的連結,指向 target。除了一個可能的異常外,沒有其他引數會傳遞給完成回撥函式。

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

type 引數僅在 Windows 上可用,在其他平臺上會被忽略。它可以設定為 'dir''file''junction'。如果 type 引數為 null,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 在不同平臺上的表現不完全一致,並且在某些情況下不可用。

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

fs.watch API 不提供任何針對檔案系統上惡意行為的保護。例如,在 Windows 上,它是透過監視目錄中的更改而不是特定檔案來實現的。這允許替換一個檔案,而 fs 會報告在新檔案上發生了具有相同檔名的更改。

可用性#

此功能依賴於底層作業系統提供檔案系統變更通知的方式。

  • 在 Linux 系統上,它使用 inotify(7)
  • 在 BSD 系統上,它使用 kqueue(2)
  • 在 macOS 上,它對檔案使用 kqueue(2),對目錄使用 FSEvents
  • 在 SunOS 系統(包括 Solaris 和 SmartOS)上,它使用 event ports
  • 在 Windows 系統上,此功能依賴於 ReadDirectoryChangesW
  • 在 AIX 系統上,此功能依賴於 AHAFS,該功能必須被啟用。
  • 在 IBM i 系統上,不支援此功能。

如果由於某種原因底層功能不可用,那麼 fs.watch() 將無法工作,並可能丟擲異常。例如,在使用虛擬化軟體(如 Vagrant 或 Docker)時,監視網路檔案系統(NFS、SMB 等)或主機檔案系統上的檔案或目錄可能不可靠,在某些情況下甚至不可能。

仍然可以使用 fs.watchFile(),它使用 stat 輪詢,但這種方法更慢且可靠性較低。

Inodes#

在 Linux 和 macOS 系統上,fs.watch() 將路徑解析為一個 inode 並監視該 inode。如果被監視的路徑被刪除並重新建立,它會被分配一個新的 inode。監視器會為刪除操作觸發一個事件,但會繼續監視*原始*的 inode。新 inode 的事件將不會被觸發。這是預期的行為。

AIX 檔案在檔案的整個生命週期內保留相同的 inode。在 AIX 上儲存並關閉一個被監視的檔案將導致兩次通知(一次用於新增新內容,一次用於截斷)。

filename 引數#

在回撥中提供 filename 引數僅在 Linux、macOS、Windows 和 AIX 上受支援。即使在支援的平臺上,也不能保證總是提供 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 接收兩個引數:當前的 stat 物件和之前的 stat 物件。

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}`);
}); 

這些 stat 物件是 fs.Stat 的例項。如果 bigint 選項為 true,這些物件中的數值將被指定為 BigInt

要收到檔案被修改而不僅僅是被訪問的通知,需要比較 curr.mtimeMsprev.mtimeMs

fs.watchFile 操作導致 ENOENT 錯誤時,它將呼叫一次監聽器,所有欄位都為零(或者對於日期,是 Unix 紀元時間)。如果之後檔案被建立,監聽器將被再次呼叫,並附帶最新的 stat 物件。這是自 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()ed 版本被呼叫,它會返回一個 Promise,該 Promise 解析為一個具有 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 是緩衝區,則忽略 encoding 選項。

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',資料將寫入當前位置。

回撥函式將接收三個引數:errbytesWrittenbuffersbytesWritten 是從 buffers 中寫入的位元組數。

如果此方法被 util.promisify() 處理,它將返回一個 Promise,該 Promise 解析為一個具有 bytesWrittenbuffers 屬性的 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 中任意值的位或(bitwise 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])#

  • src <string> | <URL> 要複製的源路徑。
  • dest <string> | <URL> 要複製到的目標路徑。
  • options <Object>
    • dereference <boolean> 解引用符號連結。預設: false
    • errorOnExist <boolean>forcefalse 且目標存在時,丟擲錯誤。預設: false
    • filter <Function> 用於過濾被複制檔案/目錄的函式。返回 true 以複製該項,返回 false 以忽略它。當忽略一個目錄時,其所有內容也將被跳過。預設值: undefined
      • src <string> 要複製的源路徑。
      • dest <string> 要複製到的目標路徑。
      • 返回: <boolean> 任何可強制轉換為 boolean 的非 Promise 值。
    • force <boolean> 覆蓋現有的檔案或目錄。如果將此設定為 false 且目標存在,複製操作將忽略錯誤。使用 errorOnExist 選項來更改此行為。預設: true
    • mode <integer> 複製操作的修飾符。預設值: 0。參見 fs.copyFileSync()mode 標誌。
    • preserveTimestamps <boolean> 當為 true 時,將保留 src 的時間戳。預設: false
    • recursive <boolean> 遞迴複製目錄 預設: false
    • verbatimSymlinks <boolean> 當為 true 時,將跳過符號連結的路徑解析。預設: false

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

將目錄複製到另一個目錄時,不支援萬用字元,行為類似於 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.globSync(pattern[, options])#

  • pattern <string> | <string[]>
  • options <Object>
    • cwd <string> | <URL> 當前工作目錄。預設: process.cwd()
    • exclude <Function> | <string[]> 用於過濾檔案/目錄的函式,或要排除的 glob 模式列表。如果提供函式,返回 true 以排除專案,返回 false 以包含專案。預設值:undefined
    • withFileTypes <boolean> 如果 glob 應返回 Dirents 形式的路徑,則為 true,否則為 false預設: false
  • 返回: <string[]> 匹配模式的檔案路徑。
import { globSync } from 'node:fs';

console.log(globSync('**/*.js'));const { globSync } = require('node:fs');

console.log(globSync('**/*.js'));

fs.lchmodSync(path, mode)#

穩定性: 0 - 廢棄

更改符號連結的許可權。返回 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)#

existingPathnewPath 建立一個新的連結。有關更多詳細資訊,請參閱 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.mkdtempDisposableSync(prefix[, options])#

返回一個可釋放的物件,其 path 屬性儲存著建立的目錄路徑。當該物件被釋放時,如果目錄仍然存在,它及其內容將被移除。如果目錄無法刪除,釋放操作將丟擲錯誤。該物件有一個 remove() 方法,可以執行相同的任務。

有關詳細資訊,請參閱 fs.mkdtemp() 的文件。

此 API 沒有基於回撥的版本,因為它設計用於 using 語法。

可選的 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 時,procfs 檔案系統必須掛載在 /proc 上才能使此函式正常工作。Glibc 沒有此限制。

fs.renameSync(oldPath, newPath)#

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

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

fs.rmdirSync(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object> 目前沒有公開的選項。以前曾有用於 recursivemaxBusyTriesemfileWait 的選項,但它們已被棄用和移除。為了向後相容,仍然接受 options 引數,但不會使用它。

同步的 rmdir(2)。返回 undefined

對檔案(非目錄)使用 fs.rmdirSync() 會在 Windows 上導致 ENOENT 錯誤,在 POSIX 上導致 ENOTDIR 錯誤。

要獲得類似於 Unix 命令 rm -rf 的行為,請使用帶有選項 { recursive: true, force: true }fs.rmSync()

fs.rmSync(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>
    • force <boolean> 當為 true 時,如果 path 不存在,異常將被忽略。預設值:false
    • maxRetries <integer> 如果遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 錯誤,Node.js 將在每次嘗試時以 retryDelay 毫秒的線性退避等待時間重試操作。此選項表示重試次數。如果 recursive 選項不為 true,則此選項將被忽略。預設值:0
    • recursive <boolean> 如果為 true,則執行遞迴目錄刪除。在遞迴模式下,操作失敗時會重試。預設值:false
    • retryDelay <integer> 兩次重試之間等待的時間(以毫秒為單位)。如果 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])#

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

fs.truncateSync(path[, len])#

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

傳遞檔案描述符已棄用,並可能在將來導致丟擲錯誤。

fs.unlinkSync(path)#

同步的 unlink(2)。返回 undefined

fs.utimesSync(path, atime, mtime)#

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

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

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 變體(promise、回撥和同步)共享。

類: 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()#

非同步關閉目錄的底層資源控制代碼。隨後的讀取將導致錯誤。

返回一個 promise,該 promise 將在資源關閉後被 fulfill。

dir.close(callback)#

非同步關閉目錄的底層資源控制代碼。隨後的讀取將導致錯誤。

在資源控制代碼關閉後,將呼叫 callback

dir.closeSync()#

同步關閉目錄的底層資源控制代碼。隨後的讀取將導致錯誤。

dir.path#

此目錄的只讀路徑,即提供給 fs.opendir()fs.opendirSync()fsPromises.opendir() 的路徑。

dir.read()#

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

返回一個 promise,該 promise 將使用一個 <fs.Dirent> 來 fulfill,或者如果沒有更多目錄條目可讀,則為 null

此函式返回的目錄條目沒有特定順序,由作業系統的底層目錄機制提供。在遍歷目錄時新增或刪除的條目可能不包含在迭代結果中。

dir.read(callback)#

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

讀取完成後,將使用一個 <fs.Dirent> 來呼叫 callback,或者如果沒有更多目錄條目可讀,則為 null

此函式返回的目錄條目沒有特定順序,由作業系統的底層目錄機制提供。在遍歷目錄時新增或刪除的條目可能不包含在迭代結果中。

dir.readSync()#

同步讀取下一個目錄條目,並作為 <fs.Dirent> 返回。有關更多詳細資訊,請參閱 POSIX readdir(3) 文件。

如果沒有更多目錄條目可讀,將返回 null

此函式返回的目錄條目沒有特定順序,由作業系統的底層目錄機制提供。在遍歷目錄時新增或刪除的條目可能不包含在迭代結果中。

dir[Symbol.asyncIterator]()#

非同步迭代目錄,直到所有條目都被讀取。有關更多詳細資訊,請參閱 POSIX readdir(3) 文件。

非同步迭代器返回的條目始終是 <fs.Dirent>。來自 dir.read()null 情況在內部處理。

有關示例,請參閱 <fs.Dir>

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

dir[Symbol.asyncDispose]()#

如果目錄控制代碼是開啟的,則呼叫 dir.close(),並返回一個在釋放完成時 fulfill 的 promise。

dir[Symbol.dispose]()#

如果目錄控制代碼是開啟的,則呼叫 dir.closeSync(),並返回 undefined

類: fs.Dirent#

表示目錄條目,可以是目錄中的檔案或子目錄,由從 <fs.Dir> 讀取時返回。目錄條目是檔名和檔案型別對的組合。

此外,當使用 withFileTypes 選項為 true 呼叫 fs.readdir()fs.readdirSync() 時,結果陣列將填充 <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> 物件描述了一個套接字,則返回 true

dirent.isSymbolicLink()#

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

dirent.name#

這個 <fs.Dirent> 物件所引用的檔名。此值的型別由傳遞給 fs.readdir()fs.readdirSync()options.encoding 決定。

dirent.parentPath#

<fs.Dirent> 物件所引用的檔案的父目錄路徑。

類: 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'ed),因此通常不需要呼叫 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'ed),因此通常不需要呼叫 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#

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

類: fs.Stats#

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

fs.stat()fs.lstat()fs.fstat() 及其同步對應方法返回的物件都屬於此型別。如果傳遞給這些方法的 options 中的 bigint 為 true,則數值將是 bigint 而不是 number,並且物件將包含以 Ns 為字尾的額外納秒精度屬性。不應直接使用 new 關鍵字建立 Stat 物件。

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> 物件描述了一個套接字,則返回 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 紀元以來的毫秒數表示。

stats.mtimeMs#

表示該檔案最後一次被修改的時間戳,以 POSIX 紀元以來的毫秒數表示。

stats.ctimeMs#

表示該檔案狀態最後一次被更改的時間戳,以 POSIX 紀元以來的毫秒數表示。

stats.birthtimeMs#

表示該檔案的建立時間戳,以 POSIX 紀元以來的毫秒數表示。

stats.atimeNs#

僅當生成該物件的方法中傳入了 bigint: true 時才存在。表示該檔案最後一次被訪問的時間戳,以 POSIX 紀元以來的納秒數表示。

stats.mtimeNs#

僅當生成該物件的方法中傳入了 bigint: true 時才存在。表示該檔案最後一次被修改的時間戳,以 POSIX 紀元以來的納秒數表示。

stats.ctimeNs#

僅當生成該物件的方法中傳入了 bigint: true 時才存在。表示該檔案狀態最後一次被更改的時間戳,以 POSIX 紀元以來的納秒數表示。

stats.birthtimeNs#

僅當生成該物件的方法中傳入了 bigint: true 時才存在。表示該檔案的建立時間戳,以 POSIX 紀元以來的納秒數表示。

stats.atime#

表示該檔案最後一次被訪問的時間戳。

stats.mtime#

表示該檔案最後一次被修改的時間戳。

stats.ctime#

表示該檔案狀態最後一次被更改的時間戳。

stats.birthtime#

表示該檔案的建立時間戳。

Stat 時間值#

atimeMsmtimeMsctimeMsbirthtimeMs 屬性是儲存相應時間(以毫秒為單位)的數值。它們的精度是平臺特定的。當生成該物件的方法中傳入 bigint: true 時,這些屬性將是 bigints,否則它們將是 numbers

atimeNsmtimeNsctimeNsbirthtimeNs 屬性是儲存相應時間(以納秒為單位)的 bigints。它們僅當生成該物件的方法中傳入 bigint: true 時才存在。它們的精度是平臺特定的。

atimemtimectimebirthtime 是各種時間的 Date 物件替代表示。Date 和數值是不相連的。分配一個新的數值,或修改 Date 值,都不會反映在相應的替代表示中。

stat 物件中的時間具有以下語義:

  • atime “訪問時間”:檔案資料最後被訪問的時間。由 mknod(2)utimes(2)read(2) 系統呼叫更改。
  • mtime “修改時間”:檔案資料最後被修改的時間。由 mknod(2)utimes(2)write(2) 系統呼叫更改。
  • ctime "Change Time":檔案狀態上次更改的時間(inode 資料修改)。chmod(2)chown(2)link(2)mknod(2)rename(2)unlink(2)utimes(2)read(2)write(2) 系統呼叫會更改此時間。
  • birthtime "Birth Time":檔案建立的時間。在檔案建立時設定一次。在檔案系統不支援 `birthtime` 的情況下,此欄位可能會儲存 `ctime` 或 `1970-01-01T00:00Z`(即 Unix 紀元時間戳 `0`)。在這種情況下,此值可能大於 `atime` 或 `mtime`。在 Darwin 和其他 FreeBSD 變體上,如果使用 utimes(2) 系統呼叫將 `atime` 顯式設定為比當前 `birthtime` 更早的值,則也會設定此時間。

在 Node.js 0.12 之前,Windows 系統上的 `ctime` 表示 `birthtime`。自 0.12 版本起,`ctime` 不再是“建立時間”,並且在 Unix 系統上,它從來都不是。

類:fs.StatFs#

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

fs.statfs() 及其同步對應方法返回的物件屬於此型別。如果傳遞給這些方法的 `options` 中的 `bigint` 為 `true`,則數值將是 `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.Utf8Stream#

穩定性:1 - 實驗性

一個最佳化的 UTF-8 流寫入器,允許按需重新整理所有內部緩衝。它能正確處理 `EAGAIN` 錯誤,並允許自定義行為,例如在磁碟繁忙時丟棄內容。

事件:'close'#

當流完全關閉時,會觸發 'close' 事件。

事件:'drain'#

當內部緩衝區已充分排空以允許繼續寫入時,會觸發 'drain' 事件。

事件:'drop'#

當達到最大長度且資料將不會被寫入時,會觸發 'drop' 事件。被丟棄的資料將作為第一個引數傳遞給事件控制代碼。

事件:'error'#

當發生錯誤時,會觸發 'error' 事件。

事件:'finish'#

當流已結束並且所有資料都已重新整理到底層檔案時,會觸發 'finish' 事件。

事件:'ready'#

當流準備好接受寫入時,會觸發 'ready' 事件。

事件:'write'#

當一次寫入操作完成時,會觸發 'write' 事件。寫入的位元組數將作為第一個引數傳遞給事件處理程式。

new fs.Utf8Stream([options])#
  • options <Object>
    • append: <boolean> 將寫入內容追加到目標檔案,而不是截斷它。預設值true
    • contentMode: <string> 您可以傳送給 write 函式的資料型別,支援的值為 'utf8''buffer'預設值'utf8'
    • dest: <string> 要寫入的檔案的路徑(模式由 append 選項控制)。
    • fd: <number> 檔案描述符,由 fs.open()fs.openSync() 返回。
    • fs: <Object> 一個具有與 `fs` 模組相同 API 的物件,可用於模擬、測試或自定義流的行為。
    • fsync: <boolean> 每次寫入完成後執行一次 fs.fsyncSync()
    • maxLength: <number> 內部緩衝區的最大長度。如果一次寫入操作會導致緩衝區超過 `maxLength`,則寫入的資料將被丟棄,並觸發一個帶有被丟棄資料的 `drop` 事件。
    • maxWrite: <number> 可以寫入的最大位元組數;預設值16384
    • minLength: <number> 在重新整理之前,內部緩衝區需要被填滿的最小長度。
    • mkdir: <boolean> 當為 `true` 時,確保 `dest` 檔案的目錄存在。預設值false
    • mode: <number> | <string> 指定建立檔案的模式(參見 `fs.open()`)。
    • periodicFlush: <number> 每隔 `periodicFlush` 毫秒呼叫一次 `flush`。
    • retryEAGAIN <Function>write()writeSync()flushSync() 遇到 `EAGAIN` 或 `EBUSY` 錯誤時將呼叫的函式。如果返回值為 `true`,操作將被重試,否則將丟擲錯誤。`err` 是導致此函式被呼叫的錯誤,`writeBufferLen` 是被寫入的緩衝區長度,`remainingBufferLen` 是流未嘗試寫入的剩餘緩衝區長度。
    • sync: <boolean> 同步執行寫入操作。
utf8Stream.append#
  • <boolean> 流是追加到檔案還是截斷檔案。
utf8Stream.contentMode#
  • <string> 可以寫入流的資料型別。支援的值為 'utf8''buffer'預設值'utf8'
utf8Stream.destroy()#

立即關閉流,不重新整理內部緩衝區。

utf8Stream.end()#

平穩地關閉流,在關閉前重新整理內部緩衝區。

utf8Stream.fd#
  • <number> 正在寫入的檔案描述符。
utf8Stream.file#
utf8Stream.flush(callback)#

如果當前沒有寫入操作在進行中,則將當前緩衝區寫入檔案。如果 `minLength` 為零或已經在寫入,則不執行任何操作。

utf8Stream.flushSync()#

同步重新整理緩衝的資料。這是一個耗費資源的操作。

utf8Stream.fsync#
  • <boolean> 流是否在每次寫入操作後執行 `fs.fsyncSync()`。
utf8Stream.maxLength#
  • <number> 內部緩衝區的最大長度。如果一次寫入操作會導致緩衝區超過 `maxLength`,則寫入的資料將被丟棄,並觸發一個帶有被丟棄資料的 `drop` 事件。
utf8Stream.minLength#
  • <number> 在重新整理之前,內部緩衝區需要被填滿的最小長度。
utf8Stream.mkdir#
  • <boolean> 流是否應確保 `dest` 檔案的目錄存在。如果為 `true`,它將在目錄不存在時建立目錄。預設值:`false`。
utf8Stream.mode#
utf8Stream.periodicFlush#
  • <number> 兩次重新整理之間的毫秒數。如果設定為 `0`,將不執行週期性重新整理。
utf8Stream.reopen(file)#

就地重新開啟檔案,對日誌輪換很有用。

utf8Stream.sync#
  • <boolean> 流是同步寫入還是非同步寫入。
utf8Stream.write(data)#

當建立流時 `options.contentMode` 設定為 `utf8` 時,`data` 引數必須是字串。如果 `contentMode` 設定為 `buffer`,`data` 引數必須是 <Buffer>

utf8Stream.writing#
  • <boolean> 流當前是否正在向檔案寫入資料。
utf8Stream[Symbol.dispose]()#

呼叫 utf8Stream.destroy()

類:fs.WriteStream#

<fs.WriteStream> 的例項是使用 fs.createWriteStream() 函式建立並返回的。

事件:'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#

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

fs.constants#

返回一個包含檔案系統操作常用常量的物件。

FS 常量#

以下常量由 `fs.constants` 和 `fsPromises.constants` 匯出。

並非所有常量在每個作業系統上都可用;這對於 Windows 尤其重要,因為許多 POSIX 特定的定義在 Windows 上不可用。對於可移植的應用程式,建議在使用前檢查它們是否存在。

要使用多個常量,請使用按位或 `|` 運算子。

示例

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 如果存在,複製操作將嘗試建立寫時複製(copy-on-write)的 reflink。如果底層平臺不支援寫時複製,則會使用備用的複製機制。
COPYFILE_FICLONE_FORCE 如果存在,複製操作將嘗試建立寫時複製(copy-on-write)的 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_APPEND`、`O_CREAT`、`O_EXCL`、`O_RDONLY`、`O_RDWR`、`O_TRUNC`、`O_WRONLY` 和 `UV_FS_O_FILEMAP` 可用。

檔案型別常量#

以下常量旨在與 <fs.Stats> 物件的 `mode` 屬性一起使用,以確定檔案型別。

常量 描述
S_IFMT 用於提取檔案型別程式碼的位掩碼。
S_IFREG 常規檔案的檔案型別常量。
S_IFDIR 目錄的檔案型別常量。
S_IFCHR 面向字元的裝置檔案的檔案型別常量。
S_IFBLK 面向塊的裝置檔案的檔案型別常量。
S_IFIFO FIFO/管道的檔案型別常量。
S_IFLNK 符號連結的檔案型別常量。
S_IFSOCK 套接字的檔案型別常量。

在 Windows 上,只有 `S_IFCHR`、`S_IFDIR`、`S_IFLNK`、`S_IFMT` 和 `S_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_IRUSR` 和 `S_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;
  }
}); 

基於 Promise 的 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();
} 

執行緒池的使用#

所有基於回撥和 Promise 的檔案系統 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()` 來重置檔案內容。