Node中有一组流API,可以像处理网络流一样处理文件。流API很方便,但要求只能以连续的方式处理文件。如果需要在指定位置进行读写,流API就行不通了,所以需要用到一些更底层都操作。
本文主要内容:
Node与文件有关的API很多与UNIX很像,使用文件描述符的方法就和UNIX中的一样。文件描述符句柄在Node中也是一个整数,代表进程文件描述符表的某个入口的索引。
有三个特殊的文件描述符:
一旦进程启动完毕,就能使用上述几个文件描述符,他们并不对应实际的文件。与操作网络流相似,不能在文件内指定位置读写,使用文件描述符只能连续的读写,就是说,举个例,在写的时候就不能去更改已经写入的东西了。
文件则不受这样的限制。
几乎所有对文件的操作都需要对文件路径进行处理,所以需要掌握。
路径分为绝对路径和相对路径,这个就不再赘述。
在Node中可以使用字符串处理路径,但是,例如当你想连接路径的不同部分时,有些是以“/”结尾而有些不是,且不同操作系统路径分隔符也不同。。。
但是Node中有一个path模块,可以帮助你规范化、连接和解析路径,还有其他好用的一些功能。该模块只是对字符串进行处理,二不需要通过和文件系统交互来进行一些验证或功能。
由用户输入或者由配置文件获取的路径,还有多个路径连接得到的路径通常都需要规范化。
可以使用path模块中的normalize()
函数来处理,他能处理.、//
等等字符。
例如:
const path = require("path");
path.normalize("/foo/bar//baz/x/..");
// 处理返回'/foo/bar/baz/x'
使用path.join()
可以连接任意个路径字符串:
const path = require(’path’);
path.join(’/foo’,’bar’,‘x/y’);
// 处理返回:'/foo/bar/x/y'
// 会自动规范化
使用path.resolve()
将多个路径解析为规范化的绝对路径。该函数的作用是,就像对路径挨个cd一样,不过,这里的路径可以为文件,并且可以不存在,只是对路径字符串的处理。
const path = require('path');
path.resolve('/foo/bar','./baz'); // /foo/bar/baz
path.resolve('/foo/bar','/tmp/file/'); // /tmp/file
如果解析结果不是绝对路径,那么会将当前工作目录的路径加到前面。
path.relative(‘/data/x/y/z‘,’/data/x/a/b’);
// => ../../a/b
如果你在’/foo/my.md’,你想获取’/foo’里面的内容,或者读取相同目录下的其他文件,可以使用dirname
获取文件路径的目录部分。
path.dirname("/foo/bar/my.md"); // /foo/bar
而提取文件名,可以用basename
。这个函数第一个接受一个路径,返回最后一个/后面的所有内容。
他还有第二个可选参数,如果你传入文件的扩展名,那么就会返回扩展名而没有文件名。但是这样很鸡肋,你必须事先知道扩展名才能获取到。
所以还可以用extname()
,这样可以直接拿到扩展名。但是注意:
/foo/x => ""
/foo/x.html => ".html"
/foo/. => ""
/foo/x. => "."
使用exist()
,返回的是布尔值。
注意,Node 0.8之后
fs.exists
代替了path.exist
,二者在语义上没有区别
const fs = require('fs');
fs.exists("路径",function(e){
// 回调,e是exists的返回值,布尔值
})
因为path.exists()
进行了IO操作,所以是异步的,需要回调函数。而path.existsSync()
,是同步的,功能一样,但不需要回调,而是直接返回返回值。