2.3 File System
File System是Node中使用最为频繁的模块之一,该模块提供了读写文件的能力,是借助于底层的linuv的C++ API来实现的。如果读者关注其底层实现,可以阅读相关的源码。
我们知道,浏览器中的JavaScript没有读写本地文件系统的能力(忽略IE中的ActiveX),而Node作为服务器编程语言,文件系统API是必需的,File System模块包含了数十个用于文件操作的API,大多提供同步和异步两种版本。
关于File System本身并没有什么特别值得关注的地方,本节也仅仅是罗列了一些常用的API,虽然开发者可以随时随地查阅在线API文档,但有些内容还是需要牢记在心。
下面列出了File System大部分API(只保留了异步版本的):
- fs.access(path[, mode], callback)
- fs.appendFile(file,data[,options], callback)
- fs.chmod(path, mode, callback)
- fs.chown(path, uid, gid, callback)
- fs.close(fd, callback)
- fs.fchmod(fd, mode, callback)
- fs.fchown(fd, uid, gid, callback)
- fs.fdatasync(fd, callback)
- fs.fstat(fd, callback)
- fs.fsync(fd, callback)
- fs.ftruncate(fd, len, callback)
- fs.futimes(fd, atime, mtime, callback)
- fs.link(existingPath, newPath, callback)
- fs.lstat(path, callback)
- fs.mkdir(path[, mode], callback)
- fs.open(path, flags[, mode], callback)
- fs.read(fd, buffer, offset, length, position, callback)
- fs.readdir(path[, options], callback)
- fs.readFile(file[, options], callback)
- fs.readlink(path[, options], callback)
- fs.rename(oldPath,newPath,callback)
- fs.rmdir(path, callback)
- fs.stat(path, callback)
- fs.symlink(target,path[, type], callback)
- fs.truncate(path, len, callback)
- fs.unlink(path, callback)
- fs.unwatchFile(filename[, listener])
- fs.utimes(path, atime, mtime, callback)
- fs.watch(filename[, options][, listener])
- fs.watchFile(filename[,options], listener)
- fs.write(fd, buffer, offset, length[, position], callback)
- fs.write(fd, data[, position[, encoding]], callback)
- fs.writeFile(file,data[,options], callback)
下面介绍几个常用的API。
1.readFile
该方法的声明如下:
readFile方法用来异步读取文本文件中的内容,例如:
readFile会将一个文件的全部内容都读到内存中,适用于体积较小的文本文件;如果你有一个数百MB大小的文件需要读取,建议不要使用readFile而是选择stream。readFile读出的数据需要在回调方法中获取,而readFileSync直接返回文本数据内容。
如果不指定readFile的encoding配置,readFile会直接返回类似下面的Buffer格式;如果希望得到的是字符串形式,还需要调用toString方法进行转换:
2.writeFile
该方法的声明如下:
在WriteFile的第一个参数为文件名,如果不存在,则会尝试创建它(默认的flag为w)。
3.fs.stat(path, callback)
stat方法通常用来获取文件的状态。
通常开发者可以在调用open()、read(),或者write方法之前调用fs.stat方法,用来判断该文件是否存在。
代码2.6 使用stat获取文件状态
如果文件存在,result就会返回文件的状态信息,例如下面的输出结果:
如果文件不存在,则会出现Error: ENOENT: no such file or directory的错误。
和fs.fstat的区别
如果阅读Nodejs文档,发现File System模块还有一个fstat方法,其声明格式为:
这两个方法在功能上是等价的,唯一的区别是fstat方法第一个参数是文件描述符,格式为Integer,因此fstat方法通常搭配open方法使用,因为open方法返回的结果就是一个文件描述符。
这段代码和fs.stat所示例代码在功能上等价。
下面是一个例子——获取目录下的所有文件名,这是一个常见的需求,实现这个功能只需要fs.readdir以及fs.stat两个API,readdir用于获取目录下的所有文件或者子目录,stat用来判断具体每条记录是文件还是子目录,如果是子目录,则递归调用整个方法。
代码2.7 获取目录下所有的文件名
目标文件目录结构如图2-2所示。
图2-2
在循环获取文件信息的时候,为了避免嵌套层数过多而使用了fs.statSync而不是fs.stat,如果使用fs.stat,需要将后续的代码放到回调函数中。