# File System
~~~
稳定度: 3 - 稳定
~~~
文件系统模块是一个简单包装的标准 POSIX 文件 I/O 操作方法集。您可以通过调用`require('fs')`来获取该模块。文件系统模块中的所有方法均有异步和同步版本。
文件系统模块中的异步方法需要一个完成时的回调函数作为最后一个传入形参。 回调函数的构成由您调用的异步方法所决定,通常情况下回调函数的第一个形参为返回的错误信息。 如果异步操作执行正确并返回,该错误形参则为`null`或者`undefined`。
如果您使用的是同步版本的操作方法,则一旦出现错误,会以通常的抛出错误的形式返回错误。 你可以用`try`和`catch`等语句来拦截错误并使程序继续进行。
这里是一个异步版本的例子:
~~~
fs.unlink('/tmp/hello', function (err) {
if (err) throw err;
console.log('successfully deleted /tmp/hello');
});
~~~
这是同步版本的例子:
~~~
fs.unlinkSync('/tmp/hello')
console.log('successfully deleted /tmp/hello');
~~~
当使用异步版本时不能保证执行顺序,因此下面这个例子很容易出错:
~~~
fs.rename('/tmp/hello', '/tmp/world', function (err) {
if (err) throw err;
console.log('renamed complete');
});
fs.stat('/tmp/world', function (err, stats) {
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats));
});
~~~
`fs.stat`有可能在`fs.rename`前执行.要等到正确的执行顺序应该用下面的方法:
~~~
fs.rename('/tmp/hello', '/tmp/world', function (err) {
if (err) throw err;
fs.stat('/tmp/world', function (err, stats) {
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats));
});
});
~~~
在繁重的任务中,*强烈推荐*使用这些函数的异步版本.同步版本会阻塞进程,直到完成处理,也就是说会暂停所有的连接.
可以使用文件名的相对路径, 但是记住这个路径是相对于`process.cwd()`的.
大部分的文件系统(fs)函数可以忽略回调函数(callback)这个参数.如果忽略它,将会由一个默认回调函数(callback)来重新抛出(rethrow)错误.要获得原调用点的堆栈跟踪(trace)信息,需要在环境变量里设置NODE_DEBUG.
~~~
$ env NODE_DEBUG=fs node script.js
fs.js:66
throw err;
^
Error: EISDIR, read
at rethrow (fs.js:61:21)
at maybeCallback (fs.js:79:42)
at Object.fs.readFile (fs.js:153:18)
at bad (/path/to/script.js:2:17)
at Object.<anonymous> (/path/to/script.js:5:1)
<etc.>
~~~
### fs.rename(oldPath, newPath, callback)
异步版本的rename函数(2).完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.renameSync(oldPath, newPath)
同步版本的rename(2).
### fs.ftruncate(fd, len, callback)
异步版本的ftruncate(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.ftruncateSync(fd, len)
同步版本的ftruncate(2).
### fs.truncate(path, len, callback)
异步版本的truncate(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.truncateSync(path, len)
同步版本的truncate(2).
异步版本的chown.完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
异步版本的chown(2).完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.chownSync(path, uid, gid)
同步版本的chown(2).
### fs.fchown(fd, uid, gid, callback)
异步版本的fchown(2)。回调函数的参数除了出现错误时有一个错误对象外,没有其它参数。
### fs.fchownSync(fd, uid, gid)
同步版本的fchown(2).
### fs.lchown(path, uid, gid, callback)
异步版的lchown(2)。完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.lchownSync(path, uid, gid)
同步版本的lchown(2).
### fs.chmod(path, mode, callback)
异步版的 chmod(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.chmodSync(path, mode)
同步版的 chmod(2).
### fs.fchmod(fd, mode, callback)
异步版的 fchmod(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.fchmodSync(fd, mode)
同步版的 fchmod(2).
### fs.lchmod(path, mode, callback)
异步版的 lchmod(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
仅在 Mac OS X 系统下可用。
### fs.lchmodSync(path, mode)
同步版的 lchmod(2).
### fs.stat(path, callback)
异步版的 stat(2). 回调函数(callback) 接收两个参数: `(err, stats)` ,其中 `stats` 是一个 [fs.Stats](#) 对象。 详情请参考 [fs.Stats](#)
### fs.lstat(path, callback)
异步版的 lstat(2). 回调函数(callback)接收两个参数: `(err, stats)` 其中 `stats` 是一个 `fs.Stats` 对象。 `lstat()` 与 `stat()` 相同,区别在于: 若 `path` 是一个符号链接时(symbolic link),读取的是该符号链接本身,而不是它所 链接到的文件。
### fs.fstat(fd, callback)
异步版的 fstat(2). 回调函数(callback)接收两个参数: `(err, stats)` 其中 `stats` 是一个 `fs.Stats` 对象。 `fstat()` 与 `stat()` 相同,区别在于: 要读取的文件(译者注:即第一个参数)是一个文件描述符(file descriptor) `fd` 。
### fs.statSync(path)
同步版的 stat(2). 返回一个 `fs.Stats` 实例。
### fs.lstatSync(path)
同步版的 lstat(2). 返回一个 `fs.Stats` 实例。
### fs.fstatSync(fd)
同步版的 fstat(2). 返回一个 `fs.Stats` 实例。
### fs.link(srcpath, dstpath, callback)
异步版的 link(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息。
### fs.linkSync(srcpath, dstpath)
同步版的 link(2).
### fs.symlink(srcpath, dstpath, [type], callback)
异步版的 symlink(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息。 `type` 可以是 `'dir'`, `'file'`, 或者`'junction'` (默认是 `'file'`),此参数仅用于 Windows 系统(其他系统平台会被忽略)。 注意: Windows 系统要求目标路径(译者注:即 `dstpath` 参数)必须是一个绝对路径,当使用 `'junction'` 时,`dstpath` 参数会自动转换为绝对路径。
### fs.symlinkSync(srcpath, dstpath, [type])
同步版的 symlink(2).
### fs.readlink(path, callback)
异步版的 readlink(2). 回调函数(callback)接收两个参数: `(err, linkString)`.
### fs.readlinkSync(path)
同步版的 readlink(2). 返回符号链接(symbolic link)的字符串值。
### fs.realpath(path, [cache], callback)
异步版的 realpath(2). 回调函数(callback)接收两个参数: `(err, resolvedPath)`. May use `process.cwd` to resolve relative paths. `cache` is an object literal of mapped paths that can be used to force a specific path resolution or avoid additional `fs.stat` calls for known real paths.
实例:
~~~
var cache = {'/etc':'/private/etc'};
fs.realpath('/etc/passwd', cache, function (err, resolvedPath) {
if (err) throw err;
console.log(resolvedPath);
});
~~~
### fs.realpathSync(path, [cache])
realpath(2) 的同步版本。返回解析出的路径。
### fs.unlink(path, callback)
异步版的 unlink(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.unlinkSync(path)
同步版的 unlink(2).
### fs.rmdir(path, callback)
异步版的 rmdir(2). 异步版的 link(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息。
### fs.rmdirSync(path)
同步版的 rmdir(2).
### fs.mkdir(path, [mode], callback)
异步版的 mkdir(2)。 异步版的 link(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息。文件 `mode` 默认为 `0777`。
### fs.mkdirSync(path, [mode])
同步版的 mkdir(2)。
### fs.readdir(path, callback)
异步版的 readdir(3)。 读取 path 路径所在目录的内容。 回调函数 (callback) 接受两个参数 `(err, files)` 其中 `files` 是一个存储目录中所包含的文件名称的数组,数组中不包括 `'.'` 和 `'..'`。
### fs.readdirSync(path)
同步版的 readdir(3). 返回文件名数组,其中不包括 `'.'` 和 `'..'` 目录.
### fs.close(fd, callback)
异步版 close(2). 完成时的回调函数(callback)只接受一个参数:可能出现的异常信息.
### fs.closeSync(fd)
同步版的 close(2).
### fs.open(path, flags, [mode], callback)
异步版的文件打开. 详见 open(2). `flags` 可以是:
- `'r'` - 以【只读】的方式打开文件. 当文件不存在时产生异常.
- `'r+'` - 以【读写】的方式打开文件. 当文件不存在时产生异常.
- `'rs'` - 同步模式下,以【只读】的方式打开文件. 指令绕过操作系统的本地文件系统缓存.
该功能主要用于打开 NFS 挂载的文件, 因为它可以让你跳过默认使用的过时本地缓存. 但这实际上非常影响 I/O 操作的性能, 因此除非你确实有这样的需求, 否则请不要使用该标志.
注意: 这并不意味着 `fs.open()` 变成了一个同步阻塞的请求. 如果你想要一个同步阻塞的请求你应该使用 `fs.openSync()`.
- `'rs+'` - 同步模式下, 以【读写】的方式打开文件. 请谨慎使用该方式, 详细请查看 `'rs'` 的注释.
- `'w'` - 以【只写】的形式打开文件. 文件会被创建 (如果文件不存在) 或者覆盖 (如果存在).
- `'wx'` - 类似 `'w'` 区别是如果文件存在则操作会失败.
- `'w+'` - 以【读写】的方式打开文件. 文件会被创建 (如果文件不存在) 或者覆盖 (如果存在).
- `'wx+'` - 类似 `'w+'` 区别是如果文件存在则操作会失败.
- `'a'` - 以【附加】的形式打开文件,即新写入的数据会附加在原来的文件内容之后. 如果文件不存在则会默认创建.
- `'ax'` - 类似 `'a'` 区别是如果文件存在则操作会失败.
- `'a+'` - 以【读取】和【附加】的形式打开文件. 如果文件不存在则会默认创建.
- `'ax+'` - 类似 `'a+'` 区别是如果文件存在则操作会失败.
参数 `mode` 用于设置文件模式 (permission and sticky bits), 不过前提是这个文件是已存在的. 默认情况下是 `0666`, 有可读和可写权限.
该 callback 接收两个参数 `(err, fd)`.
排除 (exclusive) 标识 `'x'` (对应 open(2) 的 `O_EXCL` 标识) 保证 `path` 是一个新建的文件。 POSIX 操作系统上,即使 `path` 是一个指向不存在位置的符号链接,也会被认定为文件存在。 排除标识在网络文件系统不能确定是否有效。
在 Linux 上,无法对以追加 (append) 模式打开的文件进行指定位置的写入操作。 内核会忽略位置参数并且总是将数据追加到文件尾部。
### fs.openSync(path, flags, [mode])
`fs.open()` 的同步版.
### fs.utimes(path, atime, mtime, callback)
### fs.utimesSync(path, atime, mtime)
更改 path 所指向的文件的时间戳。
### fs.futimes(fd, atime, mtime, callback)
### fs.futimesSync(fd, atime, mtime)
更改文件描述符 (file discriptor) 所指向的文件的时间戳。
### fs.fsync(fd, callback)
异步版本的 fsync(2)。回调函数仅含有一个异常 (exception) 参数。
### fs.fsyncSync(fd)
fsync(2) 的同步版本。
### fs.write(fd, buffer, offset, length[, position], callback)
通过文件标识`fd`,向指定的文件中写入`buffer`。
`offset` 和`length` 可以确定从哪个位置开始写入buffer。
`position` 是参考当前文档光标的位置,然后从该处写入数据。如果`typeof position !== 'number'`,那么数据会从当前文档位置写入,请看pwrite(2)。
回调中会给出三个参数 `(err, written, buffer)`,`written` 说明从`buffer`写入的字节数。
注意,`fs.write`多次地在同一个文件中使用而没有等待回调是不安全的。在这种情况下,强烈推荐使用`fs.createWriteStream`。
在 Linux 上,无法对以追加 (append) 模式打开的文件进行指定位置的写入操作。 内核会忽略位置参数并且总是将数据追加到文件尾部。
### fs.write(fd, data[, position[, encoding]], callback)
把`data`写入到文档中通过指定的`fd`,如果`data`不是buffer对象的实例则会把值强制转化成一个字符串。
`position` 是参考当前文档光标的位置,然后从该处写入数据。如果`typeof position !== 'number'`,那么数据会从当前文档位置写入,请看pwrite(2)。
`encoding` 是预期得到一个字符串编码
回调会得到这些参数 `(err, written, string)`,`written`表明传入的`string`需要写入的字符串长度。注意字节的写入跟字符串写入是不一样的。请看[Buffer.byteLength](#).
与写入`buffer`不同,必须写入完整的字符串,截取字符串不是符合规定的。这是因为返回的字节的位移跟字符串的位移是不一样的。
注意,`fs.write`多次地在同一个文件中使用而没有等待回调是不安全的。在这种情况下,强烈推荐使用`fs.createWriteStream`。
在 Linux 上,无法对以追加 (append) 模式打开的文件进行指定位置的写入操作。 内核会忽略位置参数并且总是将数据追加到文件尾部。
### fs.writeSync(fd, buffer, offset, length[, position])
### fs.writeSync(fd, data[, position[, encoding]])
同步版本的`fs.write()`。返回写入的字节数。
### fs.read(fd, buffer, offset, length, position, callback)
从指定的文档标识符`fd`读取文件数据。
`buffer` 是缓冲区,数据将会写入这里。
`offset` 是开始向缓冲区 `buffer` 写入的偏移量。
`length` 是一个整形值,指定了读取的字节数。
`position` 是一个整形值,指定了从哪里开始读取文件,如果`position`为`null`,将会从文件当前的位置读取数据。
回调函数给定了三个参数, `(err, bytesRead, buffer)`, 分别为错误,读取的字节和缓冲区。
### fs.readSync(fd, buffer, offset, length, position)
`fs.read` 函数的同步版本。 返回`bytesRead`的个数。
### fs.readFile(filename, [options], callback)
- `filename` {String}
- `options` {Object}
- `encoding` {String | Null} default = `null`
- `flag` {String} default = `'r'`
- `callback` {Function}
异步读取一个文件的全部内容。举例:
~~~
fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
console.log(data);
});
~~~
回调函数传递了两个参数 `(err, data)`, `data` 就是文件的内容。
如果未指定编码方式,原生buffer就会被返回。
### fs.readFileSync(filename, [options])
`fs.readFile`的同步版本。 返回文件名为 `filename` 的文件内容。
如果 `encoding` 选项被指定, 那么这个函数返回一个字符串。如果未指定,则返回一个原生buffer。
### fs.writeFile(filename, data, [options], callback)
- `filename` {String}
- `data` {String | Buffer}
- `options` {Object}
- `encoding` {String | Null} default = `'utf8'`
- `mode` {Number} default = `438` (aka `0666` in Octal)
- `flag` {String} default = `'w'`
- `callback` {Function}
异步的将数据写入一个文件, 如果文件原先存在,会被替换。 `data` 可以是一个string,也可以是一个原生buffer。
`encoding` 选项会被忽视如果 `data` 不是string而是原生buffer。`encoding`缺省为 `'utf8'`。
实例:
~~~
fs.writeFile('message.txt', 'Hello Node', function (err) {
if (err) throw err;
console.log('It\'s saved!'); //文件被保存
});
~~~
### fs.writeFileSync(filename, data, [options])
`fs.writeFile`的同步版本。
### fs.appendFile(filename, data, [options], callback)
- `filename` {String}
- `data` {String | Buffer}
- `options` {Object}
- `encoding` {String | Null} default = `'utf8'`
- `mode` {Number} default = `438` (aka `0666` in Octal)
- `flag` {String} default = `'a'`
- `callback` {Function}
异步的将数据添加到一个文件的尾部,如果文件不存在,会创建一个新的文件。 `data` 可以是一个string,也可以是原生buffer。
实例:
~~~
fs.appendFile('message.txt', 'data to append', function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!'); //数据被添加到文件的尾部
});
~~~
### fs.appendFileSync(filename, data, [options])
`fs.appendFile`的同步版本。
### fs.watchFile(filename, [options], listener)
~~~
稳定性: 2 - 不稳定. 尽可能的话推荐使用 fs.watch 来代替。
~~~
监视`filename`指定的文件的改变. 回调函数 `listener` 会在文件每一次被访问时被调用。
第二个参数是可选的。 如果提供此参数,`options` 应该是包含两个成员`persistent`和`interval`的对象,其中`persistent`值为boolean类型。`persistent`指定进程是否应该在文件被监视(watch)时继续运行,`interval`指定了目标文件被查询的间隔,以毫秒为单位。缺省值为`{ persistent: true, interval: 5007 }`。
`listener` 有两个参数,第一个为文件现在的状态,第二个为文件的前一个状态。
~~~
fs.watchFile('message.text', function (curr, prev) {
console.log('the current mtime is: ' + curr.mtime);
console.log('the previous mtime was: ' + prev.mtime);
});
~~~
`listener`中的文件状态对象类型为`fs.Stat`。
如果你只想在文件被修改时被告知,而不是仅仅在被访问时就告知,你应当在`listener`回调函数中比较下两个状态对象的`mtime`属性。即`curr.mtime` 和 `prev.mtime`.
### fs.unwatchFile(filename, [listener])
~~~
稳定性: 2 - 不稳定. 尽可能的话推荐使用 fs.watch 来代替。
~~~
停止监视文件名为 `filename`的文件. 如果 `listener`