nodejs入门API之fs模块

Posted 他乡踏雪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nodejs入门API之fs模块相关的知识,希望对你有一定的参考价值。

  • fs模块下的类与FS常量
  • fs模块下的主要方法
  • fs的Promise API与FileHandle类

 一、fs模块下的类

1.1 fs.Dir:表示目录流的类,由 fs.opendir()fs.opendirSync() 或 fsPromises.opendir() 创建。

1.2 fs.Dirent:目录项的表现形式,通过从fs.Dir中读取返回。

1.3 fs.FSWatcher:继承自 <EventEmitter>,调用 fs.watch() 方法返回该对象。每当指定监视的文件被修改时,所有的 fs.FSWatcher 对象都会触发 \'change\' 事件。

1.4 fs.ReadStream:成功调用 fs.createReadStream() 将会返回一个新的 fs.ReadStream 对象。用于读取流。

1.5 fs.Stats:文件信息对象。从 fs.stat()fs.lstat() 和 fs.fstat() 及其同步的方法返回的对象都属于此类型。

1.6 fs.WriteStream:继承自 <stream.Writable>,管理文件写入流。

1.7 FS常量:

 1.7.1文件可访问性,用于fs.access():

F_OK :表明文件对调用进程可见。可以用来判断文件是否存在,但没有有rwx权限说明。
R_OK :表明调用进程可以读取文件。
W_OK :表明调用进程可以写入文件。
X_OK :表明调用进程可以执行文件。在window系统上无效,表现的像fs.constants.F_OK。

 1.7.2文件拷贝常量,用于fs.copyFile()。

COPYFILE_EXCL :如果目标路径已经存在,则拷贝操作将失败。
COPYFILE_FICLONE :拷贝操作将尝试创建写时拷贝连接。如果底层平台不支持写时拷贝,则使用备选拷贝机制。
COPYFILE_FICLONE_FORCE :拷贝操作将尝试创建写时拷贝连接。如果底层平台不支持写时拷贝,则拷贝失败。

 1.7.3文件打开的常量,用于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系统上有效,其它系统此标志会被忽略。

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

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

 1.7.5文件模式常量,用于fs.Stats对象的mode属性,用于决定文件的访问权限。

S_IRWXU :表明所有者可读、可写、可执行。
S_IRUSE :表明所有者可读。
S_IWUSR :表明所有者可写。
S_IXUSR :表明所有者可执行。
S_IRWXG :表明群组可读、可写、可执行。
S_IRGRP :表明群组可读。
S_IWGRP :表明群组可写。
S_IXGRP : 表明群组可执行。
S_IRWXO :表明群组可读、可写、可执行。
S_IROTH :表明其他人可读。
S_IWOTH :表明其他人可写。
S_IXOTH :表明其他人可执行。

1.8 FS文件系统标志(flag):

 a 可写、可创建、可追加。(组合标志: a+、ax、as)

——a标志用来追加写入,如果没有该文件会创建该文件。

 r 可读。(组合标志:r+、rs 、rs+)

——r标志用来读取文件,如果没有该文件会抛出异常。

 w 可写、可创建。(组合标志:w+、wx、wx+)

——w标志用来做写入操作,如果没有该文件则创建,如果有该文件则截断。

——x标志用来表示文件可执行。

——s表示同步阻塞的方式操作文件。

1.9 FS文件操作权限:

文件操作权限分为三个等级:文件所有者权限、同组用户的权限、非同组用户的权限。每组权限都用一个数值表示,该数值是由标志转换加和而来(r对应4;w对应2;x对应1)。

比如在fs.open(path[, flags[, mode]], callback)用来设置用户权限的是mode参数,该参数默认操作权限是:0o666。0o表示后面的数值为8进制,666按顺序分别对应:所有者、同组用户、非同组用户。所以这个默认参数所表示的是所有用户都具备可读、可写的权限。

 二、fs模块下的主要方法

 2.1 FS.access():测试用户对Path指定的文件或目录的权限。

fs.access(path[,mode],callback);//异步:回调函数调用时将传入可能的错误参数,如果权限检查通过就不会传入参数。
fs.accessSync(path[,mode]);//同步:如果权限检查不通过则抛出Error。否则通过的话就返回undefined。

可以使用access检查文件是否存在(F_OK)、文件是否可读(R_OK)、文件是否可写(W_OK)、文件是否可执行(X_OK)。注意windows下“X_OK”无效。

不建议在fs.open()、fs.readFile()、fs.writeFile()【打开文件、读取文件、写入文件】之前使用access,相反这些操作建议直接进行,不必要在操作之前进行检查,以免引发竞态。

 1 const file = \'package.json\';
 2 
 3 // 检查当前目录中是否存在该文件。
 4 fs.access(file, fs.constants.F_OK, (err) => {
 5   console.log(`${file} ${err ? \'不存在\' : \'存在\'}`);
 6 });
 7 
 8 // 检查文件是否可读。
 9 fs.access(file, fs.constants.R_OK, (err) => {
10   console.log(`${file} ${err ? \'不可读\' : \'可读\'}`);
11 });
12 
13 // 检查文件是否可写。
14 fs.access(file, fs.constants.W_OK, (err) => {
15   console.log(`${file} ${err ? \'不可写\' : \'可写\'}`);
16 });
17 
18 // 检查当前目录中是否存在该文件,以及该文件是否可写。
19 fs.access(file, fs.constants.F_OK | fs.constants.W_OK, (err) => {
20   if (err) {
21     console.error(
22       `${file} ${err.code === \'ENOENT\' ? \'不存在\' : \'只可读\'}`);
23   } else {
24     console.log(`${file} 存在,且它是可写的`);
25   }
26 });
27 
28 //同步检查
29 try {
30   fs.accessSync(\'etc/passwd\', fs.constants.R_OK | fs.constants.W_OK);
31   console.log(\'可以读写\');
32 } catch (err) {
33   console.error(\'无权访问\');
34 }
来源于官方文档的示例

 2.2 FS.appendFile():将数据追加到文件,如果文件不存在则创建文件。

fs.appendFile(path, data[, options], callback);//异步:options可以配置文件encoding、mode、flag【字符编码、权限值、文件可操作标志符】,如果写入一个字符串值只表示字符编码。
//callbakc:当操作不可操作时会传入error对象
fs.appendFileSync(path,data[,options]);//同步

path可以指定为已打开的文件的数字型文件描述符,用于追加文件数据。

 1 //为指定路径的文件追加数据
 2 fs.appendFile(\'message.txt\', \'追加的数据\', (err) => {
 3   if (err) throw err;
 4   console.log(\'数据已追加到文件\');
 5 });
 6 //paht为已打开的文件数字型文件描述符(fd)
 7 fs.open(\'message.txt\', \'a\', (err, fd) => {
 8   if (err) throw err;
 9   fs.appendFile(fd, \'追加的数据\', \'utf8\', (err) => {
10     fs.close(fd, (err) => {
11       if (err) throw err;
12     });
13     if (err) throw err;
14   });
15 });
16 
17 //同步示例一
18 try {
19   fs.appendFileSync(\'message.txt\', \'追加的数据\');
20   console.log(\'数据已追加到文件\');
21 } catch (err) {
22   /* 处理错误 */
23 }
24 //同步示例二
25 let fd;
26 try {
27   fd = fs.openSync(\'message.txt\', \'a\');
28   fs.appendFileSync(fd, \'追加的数据\', \'utf8\');
29 } catch (err) {
30   /* 处理错误 */
31 } finally {
32   if (fd !== undefined)
33     fs.closeSync(fd);
34 }
来自官方文档的示例

2.3 Fs.chmod():修改文件权限。

fs.chmod(path,mode,callback);//异步:回调函数除了可能的异常对象,没有其他参数。
fs.chmodSync(path,mode);//同步

关于权限设置的mode参数值详细可参考第一节中的1.8和1.9的内容。

1 fs.chmod(\'my_file.txt\', 0o775, (err) => {
2   if (err) throw err;
3   console.log(\'文件 “my_file.txt” 的权限已被更改\');
4 });
来自官方文档的示例

2.4Fs.chown():更改文件所有者和群组。

fs.chown(path,uid,gid,callback);//异步:uid-所有者id、gid-群组id
fs.chownSync(path,uid,gid);//同步

2.5FS.close():关闭文件,与此对应的是打开文件方法open()。

fs.close(fd,callback);//异步
fs.closeSync(fd);//同步

2.6Fs.constants:返回包文件系统操作常用常量的对象。

详细内容见第一节1.7。

2.8Fs.copyFile():拷贝文件。

fs.copyFile(src,dest[,flags],callback);//异步
//src:要拷贝的文件
//dest:拷贝操作的目标文件名
//flags:用于拷贝操作修饰符,详细见第一节1.7.2
//callback:除了可能发生的错误err对象没有其他参数
fs.copyFileSync(src,dest[,flags])
 1 //示例一
 2 const fs = require(\'fs\');
 3 
 4 // 默认情况下将创建或覆盖目标文件。
 5 fs.copyFile(\'源文件.txt\', \'目标文件.txt\', (err) => {
 6   if (err) throw err;
 7   console.log(\'源文件已拷贝到目标文件\');
 8 });
 9 //示例二
10 const fs = require(\'fs\');
11 const { COPYFILE_EXCL } = fs.constants;
12 
13 // 通过使用 COPYFILE_EXCL,如果目标文件存在,则操作将失败。
14 fs.copyFile(\'源文件.txt\', \'目标文件.txt\', COPYFILE_EXCL, callback);
来自官方文档的示例

2.9Fs.createReadStream(path[,options]):创建一个读取文件流对象 <fs.ReadStream>

path <string> | <Buffer> | <URL>
options <string> | <Object>
//当optiions为一个字符串时表示字符编码
//当options为对象时可以包含以下字段:
flags--文件标志
encoding--字符编码
fd--文件描述符(指向仅支持阻塞读取的字符设备)
mode--文件权限
autoClose--默认:true,在error或end事件时关闭文件描述符。当属性值为false时即使出现错误,文件描述符也不会关闭。应用程序需要关闭文件描述符来确保没有文件描述符泄露。
emitClose--默认:false,流在销毁后不会触发‘close’事件。当属性值为true改变此行为。
start--与end配合读取文件的范围。
end--默认:Infinity
highWaterMark--默认:64*1024

2.10Fs.createWriteStream(path[, options]):创建一个写入流对象<fs.WriteStream>

path <string> | <Buffer> | <URL>
options <string> | <Object>
//当options为字符串时,该值为字符编码。
//当options为对象时:
flags--文件标志符
encoding--字符编码
fd--文件描述符
mode--文件权限
autoClose--默认true,当error或finish事件是文件描述符自动关闭。为false时即使出错文件描述符也不关闭。
emitClose--默认false,流在注销时不会触发close事件,反之则出发。
start--允许再文件开头之后的某个位置写入数据

2.11Fs.existsSync(path):判断文件路径是否存在(同步,对应的异步方法已废弃)。

//如果路径存在,则返回 true,否则返回 false。
//示例:
if (fs.existsSync(\'/etc/passwd\')) {
  console.log(\'文件已存在\');
}

2.12Fs.fchmod():修改文件权限。

fs.fchmod(fd,mode,callback);//异步修改文件权限
fs.fchmodSync(fd,mode);//同步修改文件权限
//fd--文件描述符;mode--权限(0o666);callback除了可能出现的error对象没有其他参数

2.13Fs.fchown():修改文件所有者和群组。

fs.fchown(fd,uid,gid,callback);//异步修改文件所有者和群组
fs.fchownSync(fd,uid,gid);//同步修改文件所有者和群组
//fd--文件描述符;uid--所有者id;gid--群组id;callback除了出现可能的异常传入error参数以外不需要传入其他参数

2.14Fs.fdatasync():文件数据同步

fs.fdatasync(fd,callback);//异步
fs.fdatasyncSync(fd);//同步

2.15Fs.fstat():生成文件信息对象fs.Stats

fs.fstat(fd[,options],callback);//异步:optiosn只有一个bigint<boolean>字段,默认为false,意思是生成普通fs.stats对象,否则生成BigintStats对象
fs.fstatSync(fd,[options]);//同步

2.16Fs.fsync():文件同步

fs.fsync(fd,callback);//异步实现文件同步
fs.fssyncSync(fd);//同步实现文件同步

2.17Fs.ftruncate():截断文件

fs.ftruncate(fd[, len], callback);//异步
fs.ftruncateSync(fd[,len]);//同步

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

 1 //示例一
 2 console.log(fs.readFileSync(\'temp.txt\', \'utf8\'));
 3 // 打印: Node.js
 4 
 5 // 获取要截断的文件的文件描述符。
 6 const fd = fs.openSync(\'temp.txt\', \'r+\');
 7 
 8 // 将文件截断为前 4 个字节。
 9 fs.ftruncate(fd, 4, (err) => {
10   assert.ifError(err);
11   console.log(fs.readFileSync(\'temp.txt\', \'utf8\'));
12 });
13 // 打印: Node
14 
15 //示例二
16 console.log(fs.readFileSync(\'temp.txt\', \'utf8\'));
17 // 打印: Node.js
18 
19 // 获取要截断的文件的文件描述符。
20 const fd = fs.openSync(\'temp.txt\', \'r+\');
21 
22 // 将文件截断为前 10 个字节,但实际大小为 7 个字节。
23 fs.ftruncate(fd, 10, (err) => {
24   assert.ifError(err);
25   console.log(fs.readFileSync(\'temp.txt\'));
26 });
27 // 打印: <Buffer 4e 6f 64 65 2e 6a 73 00 00 00>
28 // (UTF8 的值为 \'Node.js\\0\\0\\0\')
来源官方文档的示例

2.18Fs.futimes():更改文件的时间戳

fs.futimes(fd, atime, mtime, callback);//异步
fs.futimesSync(fd, atime, mtime)//同步

2.19Fs.lchmod():修改文件权限。

fs.lchmod(path, mode, callback);//异步:只适应macOS
fs.lchmodSync(path, mode)//同步

2.20Fs.lchown():修改文件所有者与群组

fs.lchown(path, uid, gid, callback);//异步
fs.lchownSync(path, uid, gid);//同步

2.21Fs.link():给文件创建新的连接

fs.link(existingPath, newPath, callback);//异步
fs.linkSync(existingPath, newPath);//同步

2.22Fs.lstat():生成文件信息对象。

fs.lstat(path[, options], callback);//异步
fs.lstatSync(path[, options]);//同步

2.23Fs.mkdir():创建目录。

fs.mkdir(path[, options], callback);//异步
fs.mkdirSync(path[, options]);//同步

options包含两个字段:recursive<boolean>是否创建父级对象。mode配置文件权限(在windows上无效)

1 // 创建 /tmp/a/apple 目录,无论是否存在 /tmp 和 /tmp/a 目录。
2 fs.mkdir(\'/tmp/a/apple\', { recursive: true }, (err) => {
3   if (err) throw err;
4 });
来源官方文档的示例

2.24Fs.mkdtemp():创建唯一的临时目录。

fs.mkdtemp(prefix[, options], callback);//异步
fs.mkdtempSync(prefix[, options]);//同步

prefix(文件夹名称不要以x结尾);options<string | object>为一个字符串时直接表示字符编码,为对象时也只有一个encoding(字符编码)字段。

 1 //示例一
 2 fs.mkdtemp(path.join(os.tmpdir(), \'目录-\'), (err, folder) => {
 3   if (err) throw err;
 4   console.log(folder);
 5   // 打印: /tmp/目录-itXde2 或 C:\\Users\\...\\AppData\\Local\\Temp\\目录-itXde2
 6 });
 7 
 8 //示例二
 9 // 新的临时目录的父目录。
10 const tmpDir = os.tmpdir();
11 
12 // 此用法是错误的:
13 fs.mkdtemp(tmpDir, (err, folder) => {
14   if (err) throw err;
15   console.log(folder);
16   // 输出类似 `/tmpabc123`。
17   // 新的临时目录会被创建在文件系统根目录,而不是在 /tmp 目录中。
18 });
19 
20 // 此用法是正确的:
21 const { sep } = require(\'path\');
22 fs.mkdtemp(`${tmpDir}${sep}`, (err, folder) => {
23   if (err) throw err;
24   console.log(folder);
25   // 输出类似 `/tmp/abc123`。
26   // 新的临时目录会被创建在 /tmp 目录中。
27 });
来自官方文档的示例

2.25Fs.open():用于打开文件。

fs.open(path[, flags[, mode]], callback);//异步打开文件:回调函数的参数(err,fd)
fs.openSync(path[, flags, mode]);//同步打开文件:返回文件描述符fd

如果文件标志flags设置了可写,当打开文件不存在时会自动创建该文件。

2.26Fs.opendir():用于打开文件夹(目录)。

fs.opendir(path[, options], callback);//异步打开文件夹,回调函数的参数(err,dir),dir一个文件目录流对象(fs.dir对象)
fs.opendirSync(path[, options]);//同步打开文件夹:返回fs.dir

2.27Fs.read():用于读取文件。

fs.read(fd, buffer, offset, length, position, callback);//异步读取。
fs.readSync(fd, buffer, offset, length, position);//同步读取。返回 bytesRead<number> 的数量。
//fd--文件描述符
//buffer--数据将写入缓冲区
//offset--buffer写入的偏移量
//length--指定读取的字节数
//position--指定开始读取的位置
//callback--三个参数:err、bytesRead、buffer

2.28Fs.readdir():用于读取目录内容。

fs.readdir(path[, options], callback);//异步:回调函数有两个参数(err,files)
fs.readdirSync(path[, options]);//同步:返回文件名数组

读取的结果为文件名数组,如果options参数中的withFileTypes设置为true则 files 数组将包含 fs.Dirent 对象。

options参数还可以有一个字符编码字段encoding,除了设置字符编码值还可以设置为buffer,读取的文件名数组就是buffer对象。

2.29Fs.readFile():读取文件。

fs.readFile(path[, options], callback);//异步
fs.readFileSync(path[, options]);//同步:返回文件内容data<string>|<buffer>
//path <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。如果将文件描述符指定为 path,则不会自动关闭它。
//options:{encoding,flag}任何指定的文件描述符都必须支持读取。
//callback(err,data)--data<string>|<buffer>

2.30Fs.readlink():读取文件连接。

fs.readlink(path[, options], callback);//异步
fs.readlinkSync(path[, options]);//同步
//path--<string> | <Buffer> | <URL>
//options--<string>|<object> :encoding--默认‘utf8’,该值可设置为‘buffer’
//callback(err,linkstring);//当设置encoding为buffer时,文件连接将作为buffer类型,否则为string类型

2.31Fs.realpath():通过解析“.”、“..”计算规范路径。不同系统环境返回值会有差异。

fs.realpath(path[, options], callback);//异步
fs.realpathSync(path[, options]);//同步
//path--相对路径
//options--字符编码<string>|<object>:{encoding}
//callback(err,resolvedPath);resolvedPath--绝对路径

规范路径名不一定是唯一的。 硬链接和绑定装载可以通过许多路径名暴露文件系统实体。
此函数的行为类似于 realpath(3),但有一些例外
 1.在不区分大小写的文件系统上不执行大小写转换。。
 2.符号链接的最大数量与平台无关,并且通常高于本地 realpath(3) 实现支持的数量。
callback 有两个参数 (err, resolvedPath)。 可以使用 process.cwd 来解析相对路径。
仅支持可转换为 UTF8 字符串的路径。

1 function rePath(pathName) {
2     fs.realpath("./fs/"+pathName + ".txt", \'utf8\', function(err,resolvedPath){
3         if(err) throw err;
4         console.log(resolvedPath);
5     });
6 }
一个最简单的示例

2.32Fs.realpath.native():同realpath基本一致。

fs.realpath.native(path[, options], callback);//异步
fs.realpathSync.native(path[, options]);//同步
//在 Linux 上,当 Node.js 与 musl libc 链接时,procfs 文件系统必须挂载在 /proc 上才能使此功能正常工作。 Glibc 没有这个限制。

2.33Fs.rename():使用新的路径名称替换文件原来的路径名称,相当于文件剪切+重命名操作。

fs.rename(oldPath, newPath, callback);//异步
fs.renameSync(oldPath, newPath);//同步
//异步地将 oldPath 上的文件重命名为 newPath 提供的路径名。 如果 newPath 已存在,则覆盖它。
1 function rename(pathName){
2     fs.rename("./fs/"+pathName + ".txt","rename.txt",function (err) {
3         if(err) throw err;
4         console.log("重命名完成");
5     })
6 }
一个简单的示例

2.34 Fs.rmdir():用来删除文件夹。

fs.rmdir(path[, options], callback);//异步
fs.rmdirSync(path[, options]);//同步
//path--文件夹路径
//options--{emfileWait,maxBusyTries,recursive}
//emfileWait--如果发生错误,以1毫秒的频率进行回退,重试操作。该参数默认值1000毫秒,如果在这个设定的时间内重试不成功则抛出错误。
//maxBusyTries--以100毫秒为频率进行回退,重试操作。该操作默认值3,表示重试操作3次。
//recursive--如果设置为true,则执行递归删除目录,如果path不存在不抛出错误,重试该操作,知道超出重试时间或次数。
//--只能删除空文件夹

2.35Fs.stat():生成文件信息对象fs.stats。

fs.stat(path[, options], callback);//异步
fs.statSync(path[, options]);//同步--返回fs.stats
//options<object>{bigint}--bigint返回的 fs.Stats 对象中的数值是否应为 bigint 型。默认值: false。
//callback(err,stats)

2.36Fs.symlink():创建一个链接指向文件或目录。

fs.symlink(target, path[, type], callback);//异步
fs.symlinkSync(target, path[, type]);//同步
//target--目标文件或目录
//path--链接
//type--仅在windows上有用,用来指定文件类型(dir、file、junction),如果找到指定的类型则使用file类型。
//callback(err)

2.37Fs.truncate():截断文件内容。

fs.truncate(path[, len], callback);//异步callback(err)
fs.unlink(path, callback);//同步--返回undefined
//len--指定截取文件内容的字节数,从文件内容起始位置到len。(默认参数为0,表示截取文件所有内容)
//这个方法尽量不要使用fd(文件描述符)可能导致出错,尽量使用文件路径作为path,使用fd的操作可以使用fs.ftruncate()

2.38Fs.unlink():删除文件

fs.unlink(path, callback);//异步:callback(err)
fs.unlinkSync(path);//同步--返回undefined
//path--可使用路径字符串,也可以使用fd文件描述符

2.39Fs.unwatchFile():删除文件上指定的事件监听器。

fs.unwatchFile(filename[, listener]);
//filename--文件名称
//listener--监听器名称

2.40Fs.utimes():更改指定的文件或文件夹的文件系统时间戳。

fs.utimes(path, atime, mtime, callback);//callback(err)
fs.utimesSync(path, atime, mtime)
//path--文件、文件夹
//atime--Unix纪元时间的数字值、Date对象、或类似 \'123456789.0\' 的数值字符串。
//mtime--时间戳

2.41Fs.watch():给文件设置更改时的事件监听器。

fs.watch(filename[, options][, listener]);
//filename--监听的文件或目录
//options<string>|object--{persistent,recursive}--persistent指示文件已被监听,进程是否继续运行;recursive--指示应该监听所有子目录还是监听当前目录。
//listener(eventType,filename)--监听器回调函数
//eventType--事件类型\'rename\'、\'change\'
//filename--触发事件的文件名称

fs.watch不是所有平台都兼容的API,仅在macOS和windows上支持。