Node.js v10.14.2 文档


目录

fs(文件系统)#

中英对照

稳定性: 2 - 稳定的

fs 模块用于以一种类似标准 POSIX 函数的方式与文件系统进行交互。

使用方法如下:

const fs = require('fs');

所有的文件系统操作都有同步和异步两种形式。

异步形式的最后一个参数是完成时的回调函数。 传给回调函数的参数取决于具体方法,但第一个参数会保留给异常。 如果操作成功完成,则第一个参数会是 nullundefined

const fs = require('fs');

fs.unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('成功删除 /tmp/hello');
});

当使用同步操作时,任何异常都会立即抛出,可以使用 try/catch 处理异常。

const fs = require('fs');

try {
  fs.unlinkSync('/tmp/hello');
  console.log('成功删除 /tmp/hello');
} catch (err) {
  // 处理异常。
}

异步的方法不能保证执行顺序。 所以下面的例子可能会出错,因为 fs.stat() 可能在 fs.rename() 之前完成:

fs.rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  console.log('重命名完成');
});
fs.stat('/tmp/world', (err, stats) => {
  if (err) throw err;
  console.log(`文件属性: ${JSON.stringify(stats)}`);
});

要想按顺序执行操作,需要把 fs.stat() 放到 fs.rename() 的回调函数中:

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

在繁忙的进程中,建议使用异步的方法,因为同步的方法会阻塞整个进程直到完成。

大多数 fs 的方法可以省略回调函数,在这种情况下,会使用默认的回调函数。 要想追踪最初的调用点,可设置 NODE_DEBUG 环境变量。

建议不要省略异步方法的回调函数,因为未来的版本可能会导致抛出错误。

$ cat script.js
function bad() {
  require('fs').readFile('/');
}
bad();

$ env NODE_DEBUG=fs node script.js
fs.js:88
        throw backtrace;
        ^
Error: EISDIR: illegal operation on a directory, read
    <stack trace.>

文件路径#

中英对照

大部分 fs 方法的文件路径可以是字符串、Buffer、或 file: 协议的 URL

字符串路径会解析成表示绝对路径或相对路径的 UTF-8 字符序列。 相对路径会按 process.cwd() 定义的当前工作目录进行处理。

使用绝对路径的例子:

const fs = require('fs');

fs.open('/open/some/file.txt', 'r', (err, fd) => {
  if (err) throw err;
  fs.close(fd, (err) => {
    if (err) throw err;
  });
});

使用相对路径的例子(相对于 process.cwd()):

fs.open('file.txt', 'r', (err, fd) => {
  if (err) throw err;
  fs.close(fd, (err) => {
    if (err) throw err;
  });
});

Buffer 路径用于在特定的 POSIX 系统上,将路径处理成 opaque 字节序列。 单一路径中可能包含多种字符编码的子序列。 Buffer 路径也可以是相对的或绝对的。

使用绝对路径的例子:

fs.open(Buffer.from('/open/some/file.txt'), 'r', (err, fd) => {
  if (err) throw err;
  fs.close(fd, (err) => {
    if (err) throw err;
  });
});

在 Windows 上,Node.js 遵循 per-drive 工作目录的理念。 当使用驱动器路径不带反斜杠时可以观察到该特性。 例如,fs.readdirSync('c:\\') 可能会返回与 fs.readdirSync('c:') 不同的结果。 详见 MSDN路径文档

支持 URL 对象#

中英对照

对于大多数 fs 方法,pathfilename 可以传入 WHATWG URL。 只支持 file: 协议的 URL

const fs = require('fs');
const fileUrl = new URL('file:///tmp/hello');

fs.readFileSync(fileUrl);

URL 必须是绝对路径。

URL 的使用因平台而异。

在 Windows 上,携带主机名的 URL 会被转换成 UNC 路径,携带驱动器号的 URL 会被转换成本地绝对路径。 主机名和驱动器号都没有的 URL 会抛出错误:

// 在 Windows 上:

// - 携带主机名的 URL 会被转换成 UNC 路径。
// file://hostname/p/a/t/h/file => \\hostname\p\a\t\h\file
fs.readFileSync(new URL('file://hostname/p/a/t/h/file'));

// - 携带驱动器号的 URL 会被转换成绝对路径。
// file:///C:/tmp/hello => C:\tmp\hello
fs.readFileSync(new URL('file:///C:/tmp/hello'));

// - 主机名和驱动器号都没有的 URL 会抛出错误。
fs.readFileSync(new URL('file:///notdriveletter/p/a/t/h/file'));
fs.readFileSync(new URL('file:///c/p/a/t/h/file'));
// TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute

携带驱动器号的 URL 必须在驱动器号后使用 : 作为分隔符。 使用其他分隔符会抛出错误。

在其他平台上,都不支持携带主机名的 URL,使用时会抛出错误:

// 在其他平台上:

// - 不支持携带主机名的 URL。
// file://hostname/p/a/t/h/file => throw!
fs.readFileSync(new URL('file://hostname/p/a/t/h/file'));
// TypeError [ERR_INVALID_FILE_URL_PATH]: must be absolute

// - URL 会被转换成绝对路径。
// file:///tmp/hello => /tmp/hello
fs.readFileSync(new URL('file:///tmp/hello'));

包含斜杆符号('/')编码的 URL 在所有平台都会抛出错误:

// 在 Windows 上:
fs.readFileSync(new URL('file:///C:/p/a/t/h/%2F'));
fs.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 */

// 在 POSIX 上:
fs.readFileSync(new URL('file:///p/a/t/h/%2F'));
fs.readFileSync(new URL('file:///p/a/t/h/%2f'));
/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded
/ characters */

在 Windows 上,包含反斜杆符号('\')编码的 URL 也会抛出错误:

// 在 Windows 上:
fs.readFileSync(new URL('file:///C:/path/%5C'));
fs.readFileSync(new URL('file:///C:/path/%5c'));
/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded
\ or / characters */

文件描述符#

中英对照

在 POSIX 系统,内核为所有进程维护着一张当前打开着的文件与资源的表格。 每个打开的文件都会分配一个名为文件描述符的数值标识。 在系统层,所有文件系统操作使用这些文件描述符来识别与追踪每个特定的文件。 Window 系统使用了一个不同但概念类似的机制来追踪资源。 为方便用户,Node.js 抽象了不同操作系统间的差异,为所有打开的文件分配了数值的文件描述符。

fs.open() 方法用于分配一个新的文件描述符。 一旦分配了,文件描述符可用于读取数据、写入数据、或查看文件信息。

fs.open('/open/some/file.txt', 'r', (err, fd) => {
  if (err) throw err;
  fs.fstat(fd, (err, stat) => {
    if (err) throw err;
    // 各种操作

    // 必须关闭文件描述符!
    fs.close(fd, (err) => {
      if (err) throw err;
    });
  });
});

大多数操作系统会限制打开的文件描述符的数量,所以当操作完成时需关闭描述符。 如果不这样做会导致内存泄漏,最终造成应用奔溃。

线程池的使用#

中英对照

所有文件系统 API 中,除了 fs.FSWatcher() 和那些显式同步的方法之外,都使用了 libuv 的线程池,这对于某些应用程序可能会产生出乎意料问题和负面的性能影响。 详见 UV_THREADPOOL_SIZE 文档。

fs.Dirent 类#

中英对照

当调用 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

fs.FSWatcher 类#

中英对照

调用 fs.watch() 会返回一个 fs.FSWatcher 对象。

所有 fs.FSWatcher 对象都是 EventEmitter 的实例,每当监视的文件被修改时都会触发 'change' 事件。

'change' 事件#

中英对照

  • eventType <string> 发生的变化事件的类型。
  • filename <string> | <Buffer> 变化的文件名(如果是相关的或有效的)。

当被监视的目录或文件有变化时触发。 详见 fs.watch()

filename 参数可能没有,这依赖于操作系统支持。 如果 fs.watch() 被调用时 encoding 选项被设置为 'buffer',则 filename 是一个 Buffer,否则 filename 是一个 UTF-8 字符串。

例子,处理 fs.watch() 监听器:

fs.watch('./tmp', { encoding: 'buffer' }, (eventType, filename) => {
  if (filename) {
    console.log(filename);
    // 打印: <Buffer ...>
  }
});

'close' 事件#

中英对照

当 watcher 停止监视文件变化时触发。 被关闭的 fs.FSWatcher 对象在事件处理函数中不再可用。

'error' 事件#

中英对照

当监视文件发生错误时触发。 发生错误的 fs.FSWatcher 对象在事件处理函数中不再可用。

watcher.close()#

中英对照

fs.FSWatcher 停止监视文件的变化。 一旦停止,fs.FSWatcher 对象将不再可用。

fs.ReadStream 类#

中英对照

调用 fs.createReadStream() 会返回 fs.ReadStream

fs.ReadStream 都是可读流

'close' 事件#

中英对照

fs.ReadStream 的文件描述符关闭时触发。

'open' 事件#

中英对照

  • fd <integer> ReadStream 的文件描述符。

fs.ReadStream' 的文件描述符打开时触发。

'ready' 事件#

中英对照

fs.ReadStream 已准备好可以使用时触发。

'open' 事件之后立即触发。

readStream.bytesRead#

中英对照

已读取的字节数。

readStream.path#

中英对照

流正在读取的文件的路径,由 fs.createReadStream() 的第一个参数指定。

fs.Stats 类#

中英对照

fs.Stats 对象提供了文件的属性。

fs.stat()fs.lstat()fs.fstat() 及其同步方法返回的对象都是该类型。 如果传入这些方法的 options 中的 bigint 为 true,则返回的数值会是 bigint 型而不是 number 型。

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 的版本:

Stats {
  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,
  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

stats.isFIFO()#

中英对照

如果 fs.Stats 是一个先进先出(FIFO)管道,则返回 true

stats.isFile()#

中英对照

如果 fs.Stats 是一个普通文件,则返回 true

stats.isSocket()#

中英对照

如果 fs.Stats 是一个 socket,则返回 true

stats.isSymbolicLink()#

中英对照

如果 fs.Stats 是一个符号链接,则返回 true

stats.dev#

中英对照

文件所在的设备的标识。

stats.ino#

中英对照

文件的索引节点。

stats.mode#

中英对照

文件类型与模式的位域。

stats.nlink#

中英对照

文件的硬链接数。

stats.uid#

中英对照

文件所有者的用户标识。

stats.gid#

中英对照

文件所在组的群组标识。

stats.rdev#

中英对照

特殊文件的设备标识。

stats.size#

中英对照

文件的字节大小。

stats.blksize#

中英对照

用于 I/O 操作的内存块的大小。

stats.blocks#

中英对照

分配给文件的内存块的数量。

stats.atimeMs#

中英对照

最后一次访问文件的时间,单位是毫秒。

stats.mtimeMs#

中英对照

最后一次修改文件的时间,单位是毫秒。

stats.ctimeMs#

中英对照

最后一次改变文件状态的时间,单位是毫秒。

stats.birthtimeMs#

中英对照

创建文件的时间,单位是毫秒。

stats.atime#

中英对照

最后一次访问文件的时间。

stats.mtime#

中英对照

最后一次修改文件的时间。

stats.ctime#

中英对照

最后一次改变文件状态的时间。

stats.birthtime#

中英对照

创建文件的时间。

文件信息的时间#

中英对照

atimeMsmtimeMsctimeMs 以及 birthtimeMs 属性是以毫秒为单位保存相对应时间的数值。 它们的精度与平台有关。 atimemtimectime 以及 birthtime 表示各个时间的 Date 对象。 两种类型的数据没有关联性。 对数值重新赋值,或者改变 Date 的值,都不会影响到对应的属性。

stat 对象中的时间遵循以下语义:

  • atime "访问时间" - 文件数据最近被访问的时间。 会被 mknod(2)utimes(2)read(2) 系统调用改变。
  • mtime "修改时间" - 文件数据最近被修改的时间。 会被 mknod(2)utimes(2)write(2) 系统调用改变。
  • ctime "变化时间" - 文件状态最近被改变的时间(修改索引节点数据)。 会被 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 衍生系统中,如果 atime 被使用 utimes(2) 系统调用显式地设置为一个比当前 birthtime 更早的值,也会有这种情况。

在 Node.js v0.12 之前的版本中,在 Windows 上,ctime 保存 birthtime。 在 v0.12 之后的版本中,ctime 不是“创建时间”,且在 Unix 系统中一直都不是。

fs.WriteStream 类#

中英对照

WriteStream可写流

'close' 事件#

中英对照

WriteStream 的文件描述符关闭时触发。

'open' 事件#

中英对照

  • fd <integer> WriteStream 的文件描述符。

WriteStream 的文件打开时触发。

'ready' 事件#

中英对照

fs.WriteStream 已准备好可以使用时触发。

'open' 事件之后立即触发。

writeStream.bytesWritten#

中英对照

已写入的字节数。 不包括正在队列中等待写入的数据。

writeStream.path#

中英对照

流正在写入的文件的路径,由 fs.createWriteStream() 的第一个参数指定。

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

中英对照

检查 path 指定的文件或目录的用户权限。 mode 指定要执行的可访问性检查。 mode 可选的值参见文件可访问性的常量。 可以使用两个或更多个值进行位或操作来创建掩码(例如 fs.constants.W_OK | fs.constants.R_OK)。

callback 只有一个参数 err。 如果可访问性检查失败,则 err 会是一个 Error。 例子,检查 package.json 是否存在、可读或可写。

const file = 'package.json';

// 检查文件是否存在。
fs.access(file, fs.constants.F_OK, (err) => {
  console.log(`${file} ${err ? '不存在' : '存在'}`);
});

// 检查文件是否可读。
fs.access(file, fs.constants.R_OK, (err) => {
  console.log(`${file} ${err ? '不可读' : '可读'}`);
});

// 检查文件是否可写。
fs.access(file, fs.constants.W_OK, (err) => {
  console.log(`${file} ${err ? '不可写' : '可写'}`);
});

// 检查文件是否存在且可写。
fs.access(file, fs.constants.F_OK | fs.constants.W_OK, (err) => {
  if (err) {
    console.error(
      `${file} ${err.code === 'ENOENT' ? '不存在' : '只可读'}`);
  } else {
    console.log(`${file} 存在且可写`);
  }
});

不建议在调用 fs.open()fs.readFile()fs.writeFile() 之前使用 fs.access() 检查文件的可访问性。 因为其他进程可能在两个调用的间隙改变文件的状态。 应该直接打开、读取或写入文件,当文件无法访问时再处理错误。

写入文件(不推荐的用法):

fs.access('myfile', (err) => {
  if (!err) {
    console.error('文件已存在');
    return;
  }

  fs.open('myfile', 'wx', (err, fd) => {
    if (err) throw err;
    writeMyData(fd);
  });
});

写入文件(推荐的用法):

fs.open('myfile', 'wx', (err, fd) => {
  if (err) {
    if (err.code === 'EEXIST') {
      console.error('文件已存在');
      return;
    }

    throw err;
  }

  writeMyData(fd);
});

读取文件(不推荐的用法):

fs.access('myfile', (err) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('文件不存在');
      return;
    }

    throw err;
  }

  fs.open('myfile', 'r', (err, fd) => {
    if (err) throw err;
    readMyData(fd);
  });
});

读取文件(推荐的用法):

fs.open('myfile', 'r', (err, fd) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('文件不存在');
      return;
    }

    throw err;
  }

  readMyData(fd);
});

以上例子中,不推荐的用法会先检查可访问性再使用文件,而推荐的用法会直接使用文件并处理任何错误。

通常仅在不直接使用文件时才检查可访问性,例如文件的可访问性是另一个进程的信号。

fs.accessSync(path[, mode])#

中英对照

同步地检查 path 指定的文件或目录的用户权限。 mode 指定要执行的可访问性检查。 mode 可选的值参见文件可访问性的常量。 可以使用两个或更多个值进行位或操作来创建掩码(例如 fs.constants.W_OK | fs.constants.R_OK)。

如果可访问性检查失败,则抛出异常,否则返回 undefined

try {
  fs.accessSync('etc/passwd', fs.constants.R_OK | fs.constants.W_OK);
  console.log('可读可写');
} catch (err) {
  console.error('不可访问');
}

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

中英对照

异步地将数据追加到文件,如果文件不存在则创建文件。

fs.appendFile('文件.txt', '追加的数据', (err) => {
  if (err) throw err;
  console.log('数据已追加到文件');
});

如果 options 是一个字符串,则指定字符编码:

fs.appendFile('文件.txt', '追加的数据', 'utf8', callback);

path 可以是使用 fs.open() 或者 fs.openSync() 打开的文件描述符。 文件描述符不会自动关闭。

fs.open('文件.txt', 'a', (err, fd) => {
  if (err) throw err;
  fs.appendFile(fd, '追加的数据', 'utf8', (err) => {
    fs.close(fd, (err) => {
      if (err) throw err;
    });
    if (err) throw err;
  });
});

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

中英对照

同步地将数据追加到文件,如果文件不存在则创建文件。

try {
  fs.appendFileSync('文件.txt', '追加的数据');
  console.log('数据已追加到文件');
} catch (err) {
  /* 异常处理 */
}

如果 options 是一个字符串,则指定字符编码:

fs.appendFileSync('文件.txt', '追加的数据', 'utf8');

path 可以是使用 fs.open() 或者 fs.openSync() 打开的文件描述符。 文件描述符不会自动关闭。

let fd;

try {
  fd = fs.openSync('文件.txt', 'a');
  fs.appendFileSync(fd, '追加的数据', 'utf8');
} catch (err) {
  /* 异常处理 */
} finally {
  if (fd !== undefined)
    fs.closeSync(fd);
}

fs.chmod(path, mode, callback)#

中英对照

异步地改变文件的权限。 callback 只有一个参数 err

详见 chmod(2)

文件的模式#

中英对照

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 表示:

  • 文件所有者可读、可写、可执行。
  • 文件所属群组可读、可写。
  • 其他人可读、可执行。

fs.chmodSync(path, mode)#

中英对照

fs.chmod() 的同步版本。

详见 chmod(2)

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

中英对照

异步地改变文件的所有者和群组。 callback 只有一个参数 err

详见 chown(2)

fs.chownSync(path, uid, gid)#

中英对照

同步地改变文件的所有者和群组。 返回 undefinedfs.chown() 的同步版本。

详见 chown(2)

fs.close(fd, callback)#

中英对照

异步的 close(2)callback 只有一个参数 err

fs.closeSync(fd)#

中英对照

同步的 close(2)。返回 undefined

fs.constants#

中英对照

返回文件系统操作的常量的对象。 具体的常量定义在FS常量中。

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

中英对照

异步地将 src 拷贝到 dest。 默认情况下,如果 dest 已存在则覆盖文件。 callback 只有一个参数 err。 Node.js 不能保证拷贝操作的原子性。 如果目标文件打开后发生错误,则 Node.js 会删除文件。

flags 指定拷贝操作的行为。 可以使用两个或更多个值进行位或操作来创建掩码(比如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)。

  • fs.constants.COPYFILE_EXCL - 如果 dest 已存在,则拷贝失败。
  • fs.constants.COPYFILE_FICLONE - 拷贝时会创建写时拷贝(copy-on-write)链接。 如果平台不支持写时拷贝,则使用后备的拷贝机制。
  • fs.constants.COPYFILE_FICLONE_FORCE - 拷贝时会创建写时拷贝链接。 如果平台不支持写时拷贝,则拷贝失败。
const fs = require('fs');

// 默认情况下,目标文件会被创建或覆盖。
fs.copyFile('来源文件.txt', '目标文件.txt', (err) => {
  if (err) throw err;
  console.log('来源文件已拷贝到目标文件');
});

如果第三个参数是一个数值,则指定 flags:

const fs = require('fs');
const { COPYFILE_EXCL } = fs.constants;

// 因为使用了 COPYFILE_EXCL,如果目标文件已存在,则拷贝失败。
fs.copyFile('来源文件.txt', '目标文件.txt', COPYFILE_EXCL, callback);

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

中英对照

同步地将 src 拷贝到 dest。 默认情况下,如果 dest 已存在则覆盖文件。 返回 undefined。 Node.js 不能保证拷贝操作的原子性。 如果目标文件打开后发生错误,则 Node.js 会删除文件。

flags 指定拷贝操作的行为。 可以使用两个或更多个值进行位或操作来创建掩码(比如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)。

  • fs.constants.COPYFILE_EXCL - 如果 dest 已存在,则拷贝失败。
  • fs.constants.COPYFILE_FICLONE - 拷贝时会创建写时拷贝(copy-on-write)链接。 如果平台不支持写时拷贝,则使用后备的拷贝机制。
  • fs.constants.COPYFILE_FICLONE_FORCE - 拷贝时会创建写时拷贝链接。 如果平台不支持写时拷贝,则拷贝失败。
const fs = require('fs');

// 默认情况下,目标文件会被创建或覆盖。
fs.copyFileSync('来源文件.txt', '目标文件.txt');
console.log('来源文件已拷贝到目标文件');

如果第三个参数是一个数值,则指定 flags:

const fs = require('fs');
const { COPYFILE_EXCL } = fs.constants;

// 因为使用了 COPYFILE_EXCL,如果目标文件已存在,则拷贝失败。
fs.copyFileSync('来源文件.txt', '目标文件.txt', COPYFILE_EXCL);

fs.createReadStream(path[, options])#

中英对照

可读流的 highWaterMark 一般默认为 16 kb,但本方法返回的可读流默认为 64 kb。

startend 用于从文件读取指定范围的字节。 startend 都是包括在内的。 如果指定了 fd 且不指定 start,则从当前位置开始读取。

如果指定了 fd,则忽略 path。 这意味着不会触发 'open' 事件。 fd 必须是阻塞的,非阻塞的 fd 应该传给 net.Socket

如果 fd 是一个只支持阻塞读取(比如键盘或声卡)的字符设备,则读取操作在读取到数据之前不会结束。 这可以避免进程退出或者流被关闭。

const fs = require('fs');
// 从字符设备创建可读流。
const stream = fs.createReadStream('/dev/input/event0');
setTimeout(() => {
  stream.close(); // 这不会关闭流。
  // 必须手动地指示流已到尽头,流才会关闭。
  // 这不会取消读取操作的等待,进程在读取完成前不会退出。
  stream.push(null);
  stream.read(0);
}, 100);

如果 autoClose 设为 false,则文件描述符不会自动关闭,即使发生错误。 应用程序需要负责关闭它,并且确保没有文件描述符泄漏。 如果 autoClose 设为 true(默认),则文件描述符在 errorend 事件时会自动关闭。

mode 用于设置文件模式(权限),但仅限创建文件时有效。

例子,从一个大小为 100 字节的文件中读取最后 10 个字节:

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

如果 options 是一个字符串,则指定字符编码。

fs.createWriteStream(path[, options])#

中英对照

start 用于写入数据到文件的指定位置。 如果要修改文件而不是覆盖文件,则 flags 应为 r+ 而不是默认的 w

如果 autoClose 设为 true(默认),则文件描述符在 errorfinish 事件时会自动关闭。 如果 autoClose 设为 false,则文件描述符不会自动关闭,即使发生错误。 应用程序需要负责关闭它,并且确保没有文件描述符泄漏。

如果指定了 fd,则忽略 path。 这意味着不会触发 'open' 事件。 fd 必须是阻塞的,非阻塞的 fd 应该传给 net.Socket

如果 options 是一个字符串,则指定字符编码。

fs.exists(path, callback)#

暂无中英对照

稳定性: 0 - 废弃的: 使用 fs.stat() or fs.access() 代替。

Test whether or not the given path exists by checking with the file system. Then call the callback argument with either true or false:

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

The parameters for this callback are not consistent with other Node.js callbacks. Normally, the first parameter to a Node.js callback is an err parameter, optionally followed by other parameters. The fs.exists() callback has only one boolean parameter. This is one reason fs.access() is recommended instead of fs.exists().

Using fs.exists() to check for the existence of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file does not exist.

write (NOT RECOMMENDED)

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

write (RECOMMENDED)

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

    throw err;
  }

  writeMyData(fd);
});

read (NOT RECOMMENDED)

fs.exists('myfile', (exists) => {
  if (exists) {
    fs.open('myfile', 'r', (err, fd) => {
      if (err) throw err;
      readMyData(fd);
    });
  } else {
    console.error('myfile does not exist');
  }
});

read (RECOMMENDED)

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

    throw err;
  }

  readMyData(fd);
});

The "not recommended" examples above check for existence and then use the file; the "recommended" examples are better because they use the file directly and handle the error, if any.

In general, check for the existence of a file only if the file won’t be used directly, for example when its existence is a signal from another process.

fs.existsSync(path)#

中英对照

如果文件存在,则返回 true,否则返回 false

详见异步的方法 fs.exists()

虽然 fs.exists() 是废弃的,但 fs.existsSync() 不是废弃的。

fs.fchmod(fd, mode, callback)#

中英对照

异步的 fchmod(2)callback 只有一个参数 err

fs.fchmodSync(fd, mode)#

中英对照

同步的 fchmod(2)。返回 undefined

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

中英对照

异步的 fchown(2)callback 只有一个参数 err

fs.fchownSync(fd, uid, gid)#

中英对照

同步的 fchown(2)。返回 undefined

fs.fdatasync(fd, callback)#

中英对照

异步的 fdatasync(2)callback 只有一个参数 err

fs.fdatasyncSync(fd)#

中英对照

同步的 fdatasync(2)。返回 undefined

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

中英对照

异步的 fstat(2)。 回调有两个参数 (err, stats),其中 stats 是一个 fs.Stats 对象。 fstat()stat() 区别是,文件是通过文件描述符 fd 指定的。

fs.fstatSync(fd[, options])#

中英对照

同步的 fstat(2)

fs.fsync(fd, callback)#

中英对照

异步的 fsync(2)callback 只有一个参数 err

fs.fsyncSync(fd)#

中英对照

同步的 fsync(2)。返回 undefined

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

中英对照

异步的 ftruncate(2)callback 只有一个参数 err

如果文件描述符指向的文件大于 len 个字节,则只有前面 len 个字节会保留在文件中。

例子,只保留文件的前 4 个字节。

console.log(fs.readFileSync('文件.txt', 'utf8'));
// 打印: Node.js

// 获取要截断的文件的文件描述符。
const fd = fs.openSync('文件.txt', 'r+');

// 截断文件至前 4 个字节。
fs.ftruncate(fd, 4, (err) => {
  assert.ifError(err);
  console.log(fs.readFileSync('文件.txt', 'utf8'));
});
// 打印: Node

如果文件小于 len 个字节,则扩大文件,且扩大的部分用空字节('\0')填充:

console.log(fs.readFileSync('文件.txt', 'utf8'));
// 打印: Node.js

// 获取要截断的文件的文件描述符。
const fd = fs.openSync('文件.txt', 'r+');

// 截断文件至前 10 个字节,但实际大小只有 7 个字节。
fs.ftruncate(fd, 10, (err) => {
  assert.ifError(err);
  console.log(fs.readFileSync('文件.txt'));
});
// 打印: <Buffer 4e 6f 64 65 2e 6a 73 00 00 00>
// (UTF8 的值为 'Node.js\0\0\0')

最后3个字节是空字节('\0'),用于补充超出的截断。

fs.ftruncateSync(fd[, len])#

中英对照

同步的 ftruncate(2)。返回 undefined。 详见异步版本的接口 fs.ftruncate()

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

中英对照

改变文件描述符所指向的对象的文件系统时间戳。 详见 fs.utimes()

该函数不支持 AIX 7.1 以下版本,在 AIX 7.1 以下版本会返回 UV_ENOSYS 错误。

fs.futimesSync(fd, atime, mtime)#

中英对照

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

fs.lchmod(path, mode, callback)#

中英对照

异步的 lchmod(2)callback 只有一个参数 err

只在 macOS 有效。

fs.lchmodSync(path, mode)#

中英对照

同步的 lchmod(2)。返回 undefined

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

中英对照

异步的 lchown(2)callback 只有一个参数 err

fs.lchownSync(path, uid, gid)#

中英对照

同步的 lchown(2)。返回 undefined

fs.link(existingPath, newPath, callback)#

中英对照

异步的 link(2)callback 只有一个参数 err

fs.linkSync(existingPath, newPath)#

中英对照

同步的 link(2)。返回 undefined

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

中英对照

异步的 lstat(2)。 回调有两个参数 (err, stats),其中 stats 是一个 fs.Stats 对象。 lstat()stat() 的区别是,如果 path 是一个符号链接,则链接指向自身而不是文件。

fs.lstatSync(path[, options])#

中英对照

同步的 lstat(2)

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

中英对照

异步地创建目录。 callback 只有一个参数 err

如果 options 是一个整数,则指定文件的模式(权限)。 如果 options 是一个对象,则 recursive 指定是否创建父目录。

// 创建 /tmp/a/apple 目录,不管 `/tmp` 和 /tmp/a 目录是否存在。
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

参见 mkdir(2)

fs.mkdirSync(path[, options])#

中英对照

同步地创建目录。 返回 undefinedfs.mkdir() 的同步版本。

参见 mkdir(2)

fs.mkdtemp(prefix[, options], callback)#

中英对照

创建临时目录。

生成六位随机字符附加到要求的 prefix 后面,然后创建一个唯一的临时目录。

创建的目录路径会作为字符串传给回调的第二个参数。

options 参数可以是一个字符串,指定字符编码。 也可以是一个对象,其中 encoding 属性指定字符编码。

例子:

fs.mkdtemp(path.join(os.tmpdir(), '目录-'), (err, folder) => {
  if (err) throw err;
  console.log(folder);
  // 打印: /tmp/目录-itXde2 或 C:\Users\...\AppData\Local\Temp\目录-itXde2
});

fs.mkdtemp() 会直接附加六位随机选择的字符串到 prefix 字符串。 例如,指定目录 /tmp,如果要在 /tmp 里面创建临时目录,则 prefix 必须在结尾加上指定平台的路径分隔符(require('path').sep)。

// 新建的临时目录的父目录。
const tmpDir = os.tmpdir();

// 该使用方法是错误的:
fs.mkdtemp(tmpDir, (err, folder) => {
  if (err) throw err;
  console.log(folder);
  // 会打印 `/tmpabc123`。
  // 新的临时目录会被创建到文件系统的根目录,而不是在 /tmp 目录里。
});

// 该使用方法才是正确的:
const { sep } = require('path');
fs.mkdtemp(`${tmpDir}${sep}`, (err, folder) => {
  if (err) throw err;
  console.log(folder);
  // 会打印于 `/tmp/abc123`。
  // 新的临时目录会被创建在 /tmp 目录里。
});

fs.mkdtempSync(prefix[, options])#

中英对照

返回创建的目录路径。

详见异步的方法 fs.mkdtemp()

options 参数可以是一个字符串,指定字符编码。 也可以是一个对象,其中 encoding 属性指定字符编码。

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

中英对照

异步地打开文件。参见 open(2)

mode 指定文件的模式(权限),但仅在创建文件时有效。 在 Windows 上,只能使用写入权限。 参见 fs.chmod()

callback 有两个参数 (err, fd)

有些字符 (如 < > : " / \ | ? *) 在 Windows 上是保留的,参见命名文件、路径、命名空间。 在 NTFS 上,如果文件名包含冒号,则 Node.js 会打开一个文件流,参见 MSDN文档

基于 fs.open() 的方法也有以上特性,比如 fs.writeFile()fs.readFile() 等。

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

中英对照

返回文件描述符。

详见异步的方法 fs.open()

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

中英对照

fd 指定的文件中读取数据。

buffer 指定要写入数据的 buffer。

offset 指定 buffer 中开始写入的偏移量。

length 指定要读取的字节数。

position 指定文件中开始读取的偏移量。 如果 positionnull,则从文件的当前位置开始读取。

callback 有三个参数 (err, bytesRead, buffer)

如果使用 util.promisify() 版本,则 Promise 返回一个包含 bytesReadbuffer 的对象。

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

中英对照

异步的 readdir(3)。 读取目录的内容。 callback 有两个参数 (err, files),其中 files 是目录中的文件名的数组。

如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer

如果 withFileTypes 设为 true,则 files 数组中的元素是 fs.Dirent

fs.readdirSync(path[, options])#

中英对照

同步的 readdir(3)。读取目录的内容。

如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer

如果 withFileTypes 设为 true,则 files 数组中的元素是 fs.Dirent

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

中英对照

异步地读取文件的内容。

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

callback 有两个参数 (err, data),其中 data 是文件的内容。

如果没有指定 encoding,则返回原始的 buffer。

如果 options 是一个字符串,则指定字符编码:

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

如果 path 是一个目录,则 fs.readFile()fs.readFileSync() 的行为因平台而异。 在 macOS、Linux 与 Windows 上,会返回错误。 在 FreeBSD 上,会返回目录内容的描述。

// 在 macOS、Linux 与 Windows 上:
fs.readFile('<目录>', (err, data) => {
  // => [Error: EISDIR: illegal operation on a directory, read <directory>]
});

// 在 FreeBSD 上:
fs.readFile('<目录>', (err, data) => {
  // => null, <data>
});

fs.readFile() 会缓存整个文件。 为了最小化内存占用,尽可能优先使用 fs.createReadStream()

文件描述符#

中英对照

  1. 指定的文件描述符必须支持读取。
  2. 如果指定文件描述符作为 path,则不会自动关闭。
  3. 从当前位置开始读取。例如,假设文件的内容是 'Hello World' 且已经使用文件描述符读取了六个字节,则使用同一文件描述符再调用 fs.readFile() 会返回 'World' 而不是 'Hello World'

fs.readFileSync(path[, options])#

中英对照

返回文件的内容。

详见异步的方法 fs.readFile()

如果指定了 encoding,则返回字符串,否则返回 buffer。

如果 path 是一个目录,则 fs.readFileSync() 的行为因平台而异。

// 在 macOS、Linux 与 Windows 上:
fs.readFileSync('<目录>');
// => [Error: EISDIR: illegal operation on a directory, read <directory>]

// 在 FreeBSD 上:
fs.readFileSync('<目录>'); // => <data>

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

中英对照

异步的 readlink(2)。 回调有两个参数 (err, linkString)

可选的 options 参数用于传入回调的链接路径,它可以是一个字符串并指定一个字符编码,或是一个对象且由一个 encoding 属性指定使用的字符编码。 如果 encoding 设为 'buffer',则返回的链接路径会被作为 Buffer 对象传入。

fs.readlinkSync(path[, options])#

中英对照

同步的 readlink(2)。 返回符号链接的字符串值。

可选的 options 参数用于传入回调的链接路径,它可以是一个字符串并指定一个字符编码,或是一个对象且由一个 encoding 属性指定使用的字符编码。 如果 encoding 设为 'buffer',则返回的链接路径会被作为 Buffer 对象传入。

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

中英对照

返回读取的字节数。

详见异步的方法 fs.read()

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

中英对照

异步地计算文件路径,解析 ... 与符号链接。

该函数与 realpath(3) 的区别在于

  1. 在大小写不敏感的文件系统,不会执行大小写转换。

  2. 符号链接的最大数量与平台无关,通常大于原生 realpath(3) 的。

callback 有两个参数 (err, resolvedPath)。 可以使用 process.cwd 解析相对路径。

只支持可转换成 UTF8 字符串的路径。

可选的 options 参数用于传入回调的路径,它可以是一个字符串并指定一个字符编码,或是一个对象且由一个 encoding 属性指定使用的字符编码。 如果 encoding 设为 'buffer',则返回的路径会被作为 Buffer 对象传入。

如果 path 解析到 socket 或管道,则函数会返回与该对象相关的系统名称。

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

中英对照

异步的 realpath(3)

callback 有两个参数 (err, resolvedPath)

只支持可转换成 UTF8 字符串的路径。

options 参数用于传入回调的路径,它可以是一个字符串并指定一个字符编码,或是一个对象且由一个 encoding 属性指定使用的字符编码。 如果 encoding 设为 'buffer',则返回的路径会被作为 Buffer 对象传入。

fs.realpathSync(path[, options])#

中英对照

返回解析的路径。

详见异步的方法 fs.realpath()

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

中英对照

同步的 realpath(3)

只支持可转换成 UTF8 字符串的路径。

options 参数用于传入回调的路径,它可以是一个字符串并指定一个字符编码,或是一个对象且由一个 encoding 属性指定使用的字符编码。 如果 encoding 设为 'buffer',则返回的路径会被作为 Buffer 对象传入。

fs.rename(oldPath, newPath, callback)#

中英对照

异步地将 oldPath 重命名为 newPath。 如果 newPath 已存在,则覆盖文件。 callback 只有一个参数 err

参见 rename(2)

fs.rename('旧文件.txt', '新文件.txt', (err) => {
  if (err) throw err;
  console.log('已完成重命名');
});

fs.renameSync(oldPath, newPath)#

中英对照

重命名文件。同步的 rename(2)。返回 undefined

fs.rmdir(path, callback)#

中英对照

移除目录。异步的 rmdir(2)callback 只有一个参数 err

如果对文件(而不是对目录)使用 fs.rmdir(),则在 Windows 上会抛出 ENOENT,在 POSIX 上会抛出 ENOTDIR

fs.rmdirSync(path)#

中英对照

移除目录。同步的 rmdir(2)。返回 undefined

如果对文件(而不是对目录)使用 fs.rmdirSync(),则在 Windows 上会抛出 ENOENT,在 POSIX 上会抛出 ENOTDIR

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

中英对照

异步的 stat(2)。 查看文件的属性。 callback 有两个参数 (err, stats),其中 stats 是一个 fs.Stats

如果发生错误,则 err.code 会是常见系统错误之一。

不建议在调用 fs.open()fs.readFile()fs.writeFile() 之前使用 fs.stat() 检查文件是否存在。 应该直接打开、读取或写入文件,当文件无效时再处理错误。

如果要检查文件是否存在但不操作它,建议使用 fs.access()

fs.statSync(path[, options])#

中英对照

同步的 stat(2)。 详见异步的方法 fs.stat()

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

中英对照

异步的 symlink(2)callback 只有一个参数 errtype 参数可以设为 'dir''file''junction',且仅在 Windows 上有效(在其他平台上忽略)。 Windows 上使用 'junction' 要求目标路径是绝对路径。 当使用 'junction' 时,target 参数会被自动标准化为绝对路径。

例子,创建了一个名为 "new-port" 且指向 "foo" 的符号链接:

fs.symlink('./foo', './new-port', callback);

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

中英对照

返回 undefined

详见异步的方法 fs.symlink()

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

中英对照

异步的 truncate(2)callback 只有一个参数 err

第一个参数也可以是一个文件描述符,在这种情况下,fs.ftruncate() 会被调用。 但这种用法已被废弃,不建议使用。

fs.truncateSync(path[, len])#

中英对照

同步的 truncate(2)。 返回 undefined

第一个参数也可以是一个文件描述符,在这种情况下,fs.ftruncate() 会被调用。 但这种用法已被废弃,不建议使用。

fs.unlink(path, callback)#

中英对照

异步地移除文件或符号链接。 callback 只有一个参数 err

// 假设 'path/file.txt' 是一个普通文件。
fs.unlink('path/file.txt', (err) => {
  if (err) throw err;
  console.log('文件已删除');
});

fs.unlink() 不能移除目录。 要移除目录可使用 fs.rmdir()

参见 unlink(2)

fs.unlinkSync(path)#

中英对照

同步的 unlink(2)。返回 undefined

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,则会抛出错误。

fs.utimesSync(path, atime, mtime)#

中英对照

返回 undefined。 详见异步的方法 fs.utimes()

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

中英对照

监视 filename 的变化,filename 可以是文件或目录。

如果 options 是一个字符串,则指定字符编码。

listener 有两个参数 (eventType, filename)eventType 可能是 'rename''change'filename 是触发事件的文件名。

在大多数平台上,当目录中有文件出现或消失时,会触发 'rename' 事件。

listener 绑定在由 fs.FSWatcher 触发的 'change' 事件上。

注意事项#

中英对照

fs.watch 的接口不是 100% 跨平台一致的,且在某些情况下不可用。

recursive 选项只支持 macOS 和 Windows。

可用性#

中英对照

该特性依赖于底层操作系统提供的方法来通知文件系统的变化。

  • 在 Linux 系统中,使用 inotify(7)
  • 在 BSD 系统中,使用 kqueue(2)
  • 在 macOS 系统中,对文件使用 kqueue(2),对目录使用 FSEvents
  • 在 SunOS 系统(包括 Solaris 和 SmartOS)中,使用 event ports
  • 在 Windows 系统中,该特性依赖 ReadDirectoryChangesW
  • 在 Aix 系统中,该特性依赖 AHAFS 必须是启动的。

如果底层功能因某些原因不可用,则 fs.watch 也无法正常工作。 例如,当使用虚拟化软件如 Vagrant、Docker 等时,在网络文件系统(NFS、SMB 等)或主文件系统中监视文件或目录可能是不可靠的。

也可以使用基于 stat 轮询的 fs.watchFile(),但是这种方法更慢,可靠性也更低。

索引节点#

中英对照

在 Linux 或 macOS 系统中,fs.watch() 解析路径到一个索引节点,并监视该索引节点。 如果监视的路径被删除或重建,则它会被分配一个新的索引节点。 监视器会发出一个删除事件,但会继续监视原始的索引节点。 新建的索引节点的事件不会被触发。 这是正常的行为。

AIX 文件在文件的生命周期中保留相同的索引节点。 在 AIX 上保存并关闭监视的文件将触发两个通知(一个用于添加新内容,一共用于拦截)。

文件名参数#

中英对照

回调中提供的 filename 参数仅在 Linux、macOS、Windows、以及 AIX 系统上支持。 即使在支持的平台中,filename 也不能保证提供。 因此,不要以为 filename 参数总是在回调中提供,如果它是空的,需要有一定的后备逻辑。

fs.watch('somedir', (eventType, filename) => {
  console.log(`事件类型是: ${eventType}`);
  if (filename) {
    console.log(`提供的文件名: ${filename}`);
  } else {
    console.log('文件名未提供');
  }
});

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

中英对照

监视 filename 的变化。 每当文件被访问时会调用 listener

options 对象可以有一个布尔值的 persistent 属性,表明当文件正在被监视时,进程是否继续运行。 options 对象可以指定一个 interval 属性,指定目标每隔多少毫秒被轮询。 默认值为 { persistent: true, interval: 5007 }

listener 有两个参数,当前的状态对象和以前的状态对象:

fs.watchFile('文件.text', (curr, prev) => {
  console.log(`当前的最近修改时间是: ${curr.mtime}`);
  console.log(`之前的最近修改时间是: ${prev.mtime}`);
});

这里的状态对象是 fs.Stat 实例。

如果想在文件被修改而不只是访问时得到通知,则需要比较 curr.mtimeprev.mtime

fs.watchFile 的运行结果是一个 ENOENT 错误时,它会调用监听器一次,且将所有字段置零(或将日期设为 Unix 纪元)。 在 Windows 中,blksizeblocks 字段会是 undefined 而不是零。 如果文件是在那之后创建的,则监听器会被再次调用,且带上最新的状态对象。 这是在 v0.10 版之后在功能上的变化。

fs.watch()fs.watchFilefs.unwatchFile 更高效。 建议使用 fs.watch 而不是 fs.watchFilefs.unwatchFile

fs.watchFile() 所监听的文件消失并重新出现时,回调事件第二次返回的 previousStat(文件重新出现)会与第一次返回的 previousStat(文件消失)相同。

这种情况会发生在:

  • 文件被删除,然后又恢复。
  • 文件被重命名两次,且第二次重命名与其原名称相同。

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

中英对照

buffer 写入到 fd 指定的文件。

offset 指定 buffer 中要开始被写入的偏移量,length 指定要写入的字节数。

position 指定文件中要开始写入的偏移量。 如果 typeof position !== 'number',则从当前位置开始写入。参见 pwrite(2)

callback 有三个参数 (err, bytesWritten, buffer),其中 bytesWritten 指定 buffer 中已写入文件的字节数。

对同一文件多次使用 fs.write() 且不等待回调,是不安全的。 对于这种情况,建议使用 fs.createWriteStream()

在 Linux 上,当以追加模式打开文件时,不能指定写入的位置。 内核会忽略位置参数,总是将数据追加到文件的尾部。

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

中英对照

string 写入到 fd 指定的文件。 如果 string 不是一个字符串,则会强制转换成字符串。

position 指定文件中要开始写入的偏移量。 如果 typeof position !== 'number',则从当前位置开始写入。参见 pwrite(2)

encoding 指定字符串的编码。

callback 有三个参数 (err, written, string),其中 written 指定字符串中已写入文件的字节数。 写入的字节数与字符串的字符数是不同的。参见 Buffer.byteLength

对同一文件多次使用 fs.write() 且不等待回调,是不安全的。 对于这种情况,建议使用 fs.createWriteStream()

在 Linux 上,当以追加模式打开文件时,不能指定写入的位置。 内核会忽略位置参数,总是将数据追加到文件的尾部。

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

中英对照

异步地将数据写入文件,如果文件已存在,则覆盖文件。

如果 data 是一个 buffer,则忽略 encoding

const data = new Uint8Array(Buffer.from('Node.js中文网'));
fs.writeFile('文件.txt', data, (err) => {
  if (err) throw err;
  console.log('文件已保存');
});

如果 options 是一个字符串,则指定字符编码:

fs.writeFile('文件.txt', 'Node.js中文网', 'utf8', callback);

对同一个文件多次使用 fs.writeFile() 且不等待回调,是不安全的。 对于这种情况,建议使用 fs.createWriteStream()

文件描述符#

中英对照

  1. 指定的文件描述符必须支持写入。
  2. 如果指定文件描述符作为 file,则不会自动关闭。
  3. 从文件的开头开始写入。例如,假设文件的内容是 'Hello World' 且新写入的内容是 'Aloha',则文件的内容会变成 'Aloha World' 而不是 'Aloha'

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

中英对照

返回 undefined

详见异步的方法 fs.writeFile()

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

中英对照

详见异步的方法 fs.write(fd, buffer...)

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

中英对照

详见异步的方法 fs.write(fd, string...)

Promise 接口#

暂无中英对照

稳定性: 1 - 试验的

The fs.promises API provides an alternative set of asynchronous file system methods that return Promise objects rather than using callbacks. The API is accessible via require('fs').promises.

FileHandle 类#

暂无中英对照

A FileHandle object is a wrapper for a numeric file descriptor. Instances of FileHandle are distinct from numeric file descriptors in that, if the FileHandle is not explicitly closed using the filehandle.close() method, they will automatically close the file descriptor and will emit a process warning, thereby helping to prevent memory leaks.

Instances of the FileHandle object are created internally by the fsPromises.open() method.

Unlike the callback-based API (fs.fstat(), fs.fchown(), fs.fchmod(), and so on), a numeric file descriptor is not used by the promise-based API. Instead, the promise-based API uses the FileHandle class in order to help avoid accidental leaking of unclosed file descriptors after a Promise is resolved or rejected.

filehandle.appendFile(data, options)#

暂无中英对照

Asynchronously append data to this file, creating the file if it does not yet exist. data can be a string or a Buffer. The Promise will be resolved with no arguments upon success.

If options is a string, then it specifies the encoding.

The FileHandle must have been opened for appending.

filehandle.chmod(mode)#

暂无中英对照

Modifies the permissions on the file. The Promise is resolved with no arguments upon success.

filehandle.chown(uid, gid)#

暂无中英对照

Changes the ownership of the file then resolves the Promise with no arguments upon success.

filehandle.close()#

暂无中英对照

  • Returns: <Promise> A Promise that will be resolved once the underlying file descriptor is closed, or will be rejected if an error occurs while closing.

Closes the file descriptor.

const fsPromises = require('fs').promises;
async function openAndClose() {
  let filehandle;
  try {
    filehandle = await fsPromises.open('thefile.txt', 'r');
  } finally {
    if (filehandle !== undefined)
      await filehandle.close();
  }
}

filehandle.datasync()#

暂无中英对照

Asynchronous fdatasync(2). The Promise is resolved with no arguments upon success.

filehandle.fd#

暂无中英对照

  • <number> The numeric file descriptor managed by the FileHandle object.

filehandle.read(buffer, offset, length, position)#

暂无中英对照

Read data from the file.

buffer is the buffer that the data will be written to.

offset is the offset in the buffer to start writing at.

length is an integer specifying the number of bytes to read.

position is an argument specifying where to begin reading from in the file. If position is null, data will be read from the current file position, and the file position will be updated. If position is an integer, the file position will remain unchanged.

Following successful read, the Promise is resolved with an object with a bytesRead property specifying the number of bytes read, and a buffer property that is a reference to the passed in buffer argument.

filehandle.readFile(options)#

暂无中英对照

Asynchronously reads the entire contents of a file.

The Promise is resolved with the contents of the file. If no encoding is specified (using options.encoding), the data is returned as a Buffer object. Otherwise, the data will be a string.

If options is a string, then it specifies the encoding.

When the path is a directory, the behavior of fsPromises.readFile() is platform-specific. On macOS, Linux, and Windows, the promise will be rejected with an error. On FreeBSD, a representation of the directory's contents will be returned.

The FileHandle has to support reading.

If one or more filehandle.read() calls are made on a file handle and then a filehandle.readFile() call is made, the data will be read from the current position till the end of the file. It doesn't always read from the beginning of the file.

filehandle.stat([options])#

暂无中英对照

Retrieves the fs.Stats for the file.

filehandle.sync()#

暂无中英对照

Asynchronous fsync(2). The Promise is resolved with no arguments upon success.

filehandle.truncate(len)#

暂无中英对照

Truncates the file then resolves the Promise with no arguments upon success.

If the file was larger than len bytes, only the first len bytes will be retained in the file.

For example, the following program retains only the first four bytes of the file:

const fs = require('fs');
const fsPromises = fs.promises;

console.log(fs.readFileSync('temp.txt', 'utf8'));
// Prints: Node.js

async function doTruncate() {
  let filehandle = null;
  try {
    filehandle = await fsPromises.open('temp.txt', 'r+');
    await filehandle.truncate(4);
  } finally {
    if (filehandle) {
      // close the file if it is opened.
      await filehandle.close();
    }
  }
  console.log(fs.readFileSync('temp.txt', 'utf8'));  // Prints: Node
}

doTruncate().catch(console.error);

If the file previously was shorter than len bytes, it is extended, and the extended part is filled with null bytes ('\0'):

const fs = require('fs');
const fsPromises = fs.promises;

console.log(fs.readFileSync('temp.txt', 'utf8'));
// Prints: Node.js

async function doTruncate() {
  let filehandle = null;
  try {
    filehandle = await fsPromises.open('temp.txt', 'r+');
    await filehandle.truncate(10);
  } finally {
    if (filehandle) {
      // close the file if it is opened.
      await filehandle.close();
    }
  }
  console.log(fs.readFileSync('temp.txt', 'utf8'));  // Prints Node.js\0\0\0
}

doTruncate().catch(console.error);

The last three bytes are null bytes ('\0'), to compensate the over-truncation.

filehandle.utimes(atime, mtime)#

暂无中英对照

Change the file system timestamps of the object referenced by the FileHandle then resolves the Promise with no arguments upon success.

This function does not work on AIX versions before 7.1, it will resolve the Promise with an error using code UV_ENOSYS.

filehandle.write(buffer, offset, length, position)#

暂无中英对照

Write buffer to the file.

The Promise is resolved with an object containing a bytesWritten property identifying the number of bytes written, and a buffer property containing a reference to the buffer written.

offset determines the part of the buffer to be written, and length is an integer specifying the number of bytes to write.

position refers to the offset from the beginning of the file where this data should be written. If typeof position !== 'number', the data will be written at the current position. See pwrite(2).

It is unsafe to use filehandle.write() multiple times on the same file without waiting for the Promise to be resolved (or rejected). For this scenario, fs.createWriteStream() is strongly recommended.

On Linux, positional writes do not work when the file is opened in append mode. The kernel ignores the position argument and always appends the data to the end of the file.

filehandle.writeFile(data, options)#

暂无中英对照

Asynchronously writes data to a file, replacing the file if it already exists. data can be a string or a buffer. The Promise will be resolved with no arguments upon success.

The encoding option is ignored if data is a buffer.

If options is a string, then it specifies the encoding.

The FileHandle has to support writing.

It is unsafe to use filehandle.writeFile() multiple times on the same file without waiting for the Promise to be resolved (or rejected).

If one or more filehandle.write() calls are made on a file handle and then a filehandle.writeFile() call is made, the data will be written from the current position till the end of the file. It doesn't always write from the beginning of the file.

fsPromises.access(path[, mode])#

暂无中英对照

Tests a user's permissions for the file or directory specified by path. The mode argument is an optional integer that specifies the accessibility checks to be performed. Check File Access Constants for possible values of mode. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.W_OK | fs.constants.R_OK).

If the accessibility check is successful, the Promise is resolved with no value. If any of the accessibility checks fail, the Promise is rejected with an Error object. The following example checks if the file /etc/passwd can be read and written by the current process.

const fs = require('fs');
const fsPromises = fs.promises;

fsPromises.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK)
  .then(() => console.log('can access'))
  .catch(() => console.error('cannot access'));

Using fsPromises.access() to check for the accessibility of a file before calling fsPromises.open() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.

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

暂无中英对照

Asynchronously append data to a file, creating the file if it does not yet exist. data can be a string or a Buffer. The Promise will be resolved with no arguments upon success.

If options is a string, then it specifies the encoding.

The path may be specified as a FileHandle that has been opened for appending (using fsPromises.open()).

fsPromises.chmod(path, mode)#

暂无中英对照

Changes the permissions of a file then resolves the Promise with no arguments upon succces.

fsPromises.chown(path, uid, gid)#

暂无中英对照

Changes the ownership of a file then resolves the Promise with no arguments upon success.

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

暂无中英对照

Asynchronously copies src to dest. By default, dest is overwritten if it already exists. The Promise will be resolved with no arguments upon success.

Node.js makes no guarantees about the atomicity of the copy operation. If an error occurs after the destination file has been opened for writing, Node.js will attempt to remove the destination.

flags is an optional integer that specifies the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE).

  • fs.constants.COPYFILE_EXCL - The copy operation will fail if dest already exists.
  • fs.constants.COPYFILE_FICLONE - The copy operation will attempt to create a copy-on-write reflink. If the platform does not support copy-on-write, then a fallback copy mechanism is used.
  • fs.constants.COPYFILE_FICLONE_FORCE - The copy operation will attempt to create a copy-on-write reflink. If the platform does not support copy-on-write, then the operation will fail.
const fsPromises = require('fs').promises;

// destination.txt will be created or overwritten by default.
fsPromises.copyFile('source.txt', 'destination.txt')
  .then(() => console.log('source.txt was copied to destination.txt'))
  .catch(() => console.log('The file could not be copied'));

If the third argument is a number, then it specifies flags:

const fs = require('fs');
const fsPromises = fs.promises;
const { COPYFILE_EXCL } = fs.constants;

// By using COPYFILE_EXCL, the operation will fail if destination.txt exists.
fsPromises.copyFile('source.txt', 'destination.txt', COPYFILE_EXCL)
  .then(() => console.log('source.txt was copied to destination.txt'))
  .catch(() => console.log('The file could not be copied'));

fsPromises.lchmod(path, mode)#

暂无中英对照

Changes the permissions on a symbolic link then resolves the Promise with no arguments upon success. This method is only implemented on macOS.

fsPromises.lchown(path, uid, gid)#

暂无中英对照

Changes the ownership on a symbolic link then resolves the Promise with no arguments upon success.

fsPromises.link(existingPath, newPath)#

暂无中英对照

Asynchronous link(2). The Promise is resolved with no arguments upon success.

fsPromises.lstat(path[, options])#

暂无中英对照

Asynchronous lstat(2). The Promise is resolved with the fs.Stats object for the given symbolic link path.

fsPromises.mkdir(path[, options])#

暂无中英对照

Asynchronously creates a directory then resolves the Promise with no arguments upon success.

The optional options argument can be an integer specifying mode (permission and sticky bits), or an object with a mode property and a recursive property indicating whether parent folders should be created.

fsPromises.mkdtemp(prefix[, options])#

暂无中英对照

Creates a unique temporary directory and resolves the Promise with the created folder path. A unique directory name is generated by appending six random characters to the end of the provided prefix.

The optional options argument can be a string specifying an encoding, or an object with an encoding property specifying the character encoding to use.

fsPromises.mkdtemp(path.join(os.tmpdir(), 'foo-'))
  .catch(console.error);

The fsPromises.mkdtemp() method will append the six randomly selected characters directly to the prefix string. For instance, given a directory /tmp, if the intention is to create a temporary directory within /tmp, the prefix must end with a trailing platform-specific path separator (require('path').sep).

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

暂无中英对照

Asynchronous file open that returns a Promise that, when resolved, yields a FileHandle object. See open(2).

mode sets the file mode (permission and sticky bits), but only if the file was created.

Some characters (< > : " / \ | ? *) are reserved under Windows as documented by Naming Files, Paths, and Namespaces. Under NTFS, if the filename contains a colon, Node.js will open a file system stream, as described by this MSDN page.

fsPromises.readdir(path[, options])#

暂无中英对照

Reads the contents of a directory then resolves the Promise with an array of the names of the files in the directory excluding '.' and '..'.

The optional options argument can be a string specifying an encoding, or an object with an encoding property specifying the character encoding to use for the filenames. If the encoding is set to 'buffer', the filenames returned will be passed as Buffer objects.

If options.withFileTypes is set to true, the resolved array will contain fs.Dirent objects.

fsPromises.readFile(path[, options])#

暂无中英对照

Asynchronously reads the entire contents of a file.

The Promise is resolved with the contents of the file. If no encoding is specified (using options.encoding), the data is returned as a Buffer object. Otherwise, the data will be a string.

If options is a string, then it specifies the encoding.

When the path is a directory, the behavior of fsPromises.readFile() is platform-specific. On macOS, Linux, and Windows, the promise will be rejected with an error. On FreeBSD, a representation of the directory's contents will be returned.

Any specified FileHandle has to support reading.

fsPromises.readlink(path[, options])#

暂无中英对照

Asynchronous readlink(2). The Promise is resolved with the linkString upon success.

The optional options argument can be a string specifying an encoding, or an object with an encoding property specifying the character encoding to use for the link path returned. If the encoding is set to 'buffer', the link path returned will be passed as a Buffer object.

fsPromises.realpath(path[, options])#

暂无中英对照

Determines the actual location of path using the same semantics as the fs.realpath.native() function then resolves the Promise with the resolved path.

Only paths that can be converted to UTF8 strings are supported.

The optional options argument can be a string specifying an encoding, or an object with an encoding property specifying the character encoding to use for the path. If the encoding is set to 'buffer', the path returned will be passed as a Buffer object.

On Linux, when Node.js is linked against musl libc, the procfs file system must be mounted on /proc in order for this function to work. Glibc does not have this restriction.

fsPromises.rename(oldPath, newPath)#

暂无中英对照

Renames oldPath to newPath and resolves the Promise with no arguments upon success.

fsPromises.rmdir(path)#

暂无中英对照

Removes the directory identified by path then resolves the Promise with no arguments upon success.

Using fsPromises.rmdir() on a file (not a directory) results in the Promise being rejected with an ENOENT error on Windows and an ENOTDIR error on POSIX.

fsPromises.stat(path[, options])#

暂无中英对照

The Promise is resolved with the fs.Stats object for the given path.

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

暂无中英对照

Creates a symbolic link then resolves the Promise with no arguments upon success.

The type argument is only used on Windows platforms and can be one of 'dir', 'file', or 'junction'. Windows junction points require the destination path to be absolute. When using 'junction', the target argument will automatically be normalized to absolute path.

fsPromises.truncate(path[, len])#

暂无中英对照

Truncates the path then resolves the Promise with no arguments upon success. The path must be a string or Buffer.

fsPromises.unlink(path)#

暂无中英对照

Asynchronous unlink(2). The Promise is resolved with no arguments upon success.

fsPromises.utimes(path, atime, mtime)#

暂无中英对照

Change the file system timestamps of the object referenced by path then resolves the Promise with no arguments upon success.

The atime and mtime arguments follow these rules:

  • Values can be either numbers representing Unix epoch time, Dates, or a numeric string like '123456789.0'.
  • If the value can not be converted to a number, or is NaN, Infinity or -Infinity, an Error will be thrown.

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

暂无中英对照

Asynchronously writes data to a file, replacing the file if it already exists. data can be a string or a buffer. The Promise will be resolved with no arguments upon success.

The encoding option is ignored if data is a buffer.

If options is a string, then it specifies the encoding.

Any specified FileHandle has to support writing.

It is unsafe to use fsPromises.writeFile() multiple times on the same file without waiting for the Promise to be resolved (or rejected).

常量#

中英对照

以下常量由 fs.constants 输出。

不是所有的常量在每一个操作系统上都是可用的。

文件可访问性的常量#

中英对照

以下常量用于 fs.access()

常量 描述
F_OK 文件可见。 用于检查文件是否存在,但不会表明 rwx 权限。
R_OK 文件可读。
W_OK 文件可写。
X_OK 文件可执行。 在 Windows 上无效(效果同 fs.constants.F_OK)。

文件拷贝的常量#

中英对照

以下常量用于 fs.copyFile()

常量 描述
COPYFILE_EXCL 如果目标路径已存在,则拷贝操作会失败。
COPYFILE_FICLONE 拷贝操作会试图创建一个写时拷贝链接。 如果底层平台不支持写时拷贝,则使用备选的拷贝机制。
COPYFILE_FICLONE_FORCE 拷贝操作会试图创建一个写时拷贝链接。 如果底层平台不支持写时拷贝,则拷贝操作会失败。

文件打开的常量#

中英对照

以下常量用于 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 表明以非阻塞模式打开文件。

文件类型的常量#

中英对照

以下常量用于 fs.Stats 对象的 mode 属性,用来决定文件的类型。

常量 描述
S_IFMT 用于提取文件类型码的位掩码。
S_IFREG 表示常规文件。
S_IFDIR 表示目录。
S_IFCHR 表示面向字符的设备文件。
S_IFBLK 表示面向块的设备文件。
S_IFIFO 表示 FIFO 或管道。
S_IFLNK 表示符号链接。
S_IFSOCK 表示 socket。

文件模式的常量#

中英对照

以下常量用于 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 表明可被其他人执行。

文件系统 flag#

中英对照

flag 可选的值如下:

  • 'a' - 打开文件用于追加。如果文件不存在则创建文件。

  • 'ax' - 类似 'a',但如果文件已存在则抛出异常。

  • 'a+' - 打开文件用于读取和追加。如果文件不存在则创建文件。

  • 'ax+' - 类似 'a+',但如果文件已存在则抛出异常。

  • 'as' - 以同步模式打开文件用于追加。如果文件不存在则创建文件。

  • 'as+' - 以同步模式打开文件用于读取和追加。如果文件不存在则创建文件。

  • 'r' - 打开文件用于读取。如果文件不存在则抛出异常。

  • 'r+' - 打开文件用于读取和写入。如果文件不存在则抛出异常。

  • 'rs+' - 以同步模式打开文件用于读取和写入。指示操作系统绕开本地文件系统缓存。

    主要用于在 NFS 挂载上打开文件,可以跳过可能存在的本地缓存。 对 I/O 性能有较大影响,除非需要否则不建议使用。

    不会将 fs.open()fsPromises.open() 变成同步的阻塞调用。 如果期望同步的操作,应该使用类似 fs.openSync() 的方法。

  • 'w' - 打开文件用于写入。如果文件不存在,则创建文件;如果文件已存在,则截断文件。

  • 'wx' - 类似 'w',但如果文件已存在则抛出异常。

  • 'w+' - 打开文件用于读取和写入。如果文件不存在,则创建文件;如果文件已存在,则截断文件。

  • 'wx+' - 类似 'w+',但如果文件已存在则抛出异常。

flag 也可以是一个数值,参见 open(2)。 常用的常量都定义在 fs.constants 上。 在 Windows 上,flag 会被转换成等效的其他 flag,例如 O_WRONLY 转换成 FILE_GENERIC_WRITEO_EXCL|O_CREAT 转换成 CREATE_NEW

'x'open(2) 中的 O_EXCL)可以确保文件是新创建的。 在 POSIX 系统上,即使是指向不存在的文件的符号链接,也会视为文件已存在。 该 flag 在网络文件系统中可能无效。

在 Linux 上,当以追加模式打开文件时,不能指定写入的位置。 内核会忽略位置参数,总是将数据追加到文件的尾部。

如果要修改文件而不是覆盖文件,则应该使用 'r+' 而不是默认的 'w'

有些 flag 的行为因平台而异。 例如,在 macOS 和 Linux 上,以 'a+' 打开目录会返回错误。 但在 Windows 和 FreeBSD 上,则返回文件描述符或 FileHandle

// 在 macOS 和 Linux 上:
fs.open('<目录>', 'a+', (err, fd) => {
  // => [Error: EISDIR: illegal operation on a directory, open <directory>]
});

// 在 Windows 和 FreeBSD 上:
fs.open('<目录>', 'a+', (err, fd) => {
  // => null, <fd>
});

在 Windows 上,使用 'w'(无论是 fs.open()fs.writeFile()fsPromises.open())打开隐藏文件会抛出 EPERM。 隐藏文件可以使用 'r+' 打开用于写入。

调用 fs.ftruncate()fsPromises.ftruncate() 可以用于重置文件的内容。