原文链接:https://blog.risingstack.com/mastering-the-nodejs-core-modules-file-system-fs-module/
在这篇文章中,我们会看一下(Node.js的)文件系统模块,文件流和一些可选的文件模块。
想象一下这样的场景,你必须使用Node.js去完成一项任务…..
通过查官方文档,Google搜索解决方案或者在npm找一个可以解决这问题的模块,这任务看起来还是挺容易完成的。
嘛,这当然是可以的,但有时候核心模块就可以轻松地帮你完成工作(而不需要去查资料)。
通过《掌握Node.js核心模块》系列文章,你可以学习到核心模块中一些隐藏和不为人知的特性。我们也会推荐一些拓展核心模块功能的模块,对你日常的开发有极大的帮助。
Node.js 文件
模块
文件 I/O 是由简单封装的标准 POSIX 函数提供的。 通过require('fs')
使用该模块。 所有的方法都有异步和同步两种形式。
异步的API
1 | // the async api |
当你开发生产代码的时候,你应该使用异步的API,因为这不会阻止事件循环,使程序更加高效。
同步的API
1 | // the sync api |
你只应该在写demo或者小的CLI时才使用同步API。
Node.js文件流
我们很少看到程序员使用文件流。
(然而)流在Node.js中是一件强大的武器,可以使程序占用更少的内存。
在Node.js中什么是文件流?
若要处理数据,流在Node.js中是最好的。你需要理解这三个概念:
- source - 数据来源对象(译者注:理解为水的来源),
- pipeline - 数据流向的过程(你可以在这过滤或者更新数据。译者注:理解为水管),
- sink - 数据最后存放的地方(译者注:理解为开了水龙头后接水的容器)。
如果需要知道更多知识,可以看下Substack的Stream Handbook.
你可以轻松地使用流复制文件,尽管文件模块不提供相应的功能:
1 | // copy a file |
你可能会问:为什么我要这么做,不就是一个cp
命令吗?
使用流去处理文件,最大的好处是在此过程中你可以轻松地加工文件,下面是一个压缩文件的例子:
1 | const fs = require('fs') |
Node.js支持
需要从npm中得到相应模块的帮助吗?
什么时候不要使用fs.access
使用fs.access
的目的是为了检查指定文件或者目录的用户权限,例子如下:
1 | fs.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK, (err) => { |
可供权限检查的常量:
fs.constants.F_OK
- 检查该文件在进程中是否可见,
fs.constants.R_OK
- 检查该文件在进程中是否可读,
fs.constants.W_OK
- 检查该文件在进程中是否可写,
fs.constants.X_OK
- 检查该文件在进程中是否可执行。
在使用fs.open
之前,可使用fs.access
去检查文件的可访问性,但 fs.readFile
和fs.writeFile
不推荐(使用fs.access
去检查)。
理由很简单,如果你这么做,就会引入了一个竞态条件。在查询权限和操作文件中相互竞争,另外的进程可能已经修改了那个文件。
相反,你应该直接打开这文件并在这处理可能出现的错误。
慎用fs.watch
通过使用fs.watch
,当(被监听的)文件或者目录有变化时,你会收到通知。
然而,fs.watch
这个API无法跨平台百分百一致,在某些系统中根本就不可用。
在Linux系统中, 它使用inotify,
在BSD系统中,它使用kqueue,
在SunOS中(包括Solaris和SmartOS),API是event ports,
在Windows系统中, 这功能依赖于ReadDirectoryChangesW。
注意:只有OS X和Windows系统支持递归选项,Linux不支持。
还有,回调函数中的fileName
参数只在Linux和Windows系统中提供,因此你应该准备好相应的回退机制以防止它是undefined
。
1 | fs.watch('some/path', (eventType, fileName) => { |
npm中有用的文件模块
社区中维护着一些拓展了文件系统功能的模块。
graceful-fs
graceful-fs
是文件系统模块的替代模块,它优化了以下内容(译者注:由于存在太多专业名词,下面的不作翻译,请见谅):
queues up
open
andreaddir
calls, and retries them once something closes if there is an EMFILE error from too many file descriptors,ignores
EINVAL
andEPERM
errors inchown
,fchown
orlchown
if the user isn’t root,makes
lchmod
andlchown
become noops, if not available,retries reading a file if read results in
EAGAIN
error.
你可以像使用文件模块一样使用它,或者都引入它们,根据需要二选一使用。
1 | // use as a standalone module |
mock-fs
mock-fs
可以在文件系统模块中模拟数据,这可以让你使用模拟的文件或者目录进行测试。
用起来非常简单,请看下面的示例:
1 | const mock = require('mock-fs') |
lockfile
文件锁定是在同一时间只允许一个进程去操作文件。这可以避免产生竞态条件。
通过lockfile
添加文件锁是非常简单的:
1 | const lockFile = require('lockfile') |
总结
我希望这篇文章对Node.js的文件系统讲解对你有用。
如果你对这方面内容有问题,请在下面的评论中告诉我。