文件的读取与写入
fs
是 file system 的简写,表示文件系统,在 Node.js 中使用 fs
模块之前,首先需要使用 require()
方法将 fs
模块引入,代码如下:
var fs = require('fs');
检查文件是否存在
fs
模块内置许多方法,用以对文件进行相关操作。具体使用时,有的方法如果发现文件不存在,可以创建文件,而有的方法则不能,这时就会出现错误,为了避免这类错误,在对文件进行操作之前,一般都需要检测文件是否存在,并且根据需要检查文件的可读或可写等属性。检查文件是否存在及其属性可以通过 access()
方法实现,语法格式如下:
fs.access(path, mode, callback)
-
path
:文件的路径。 -
mode
:要执行的可访问性检查,默认值为fs.constants.F_OK
。查看文件访问常量以获取可能的mode
值,具体文件访问常量如表7.1所示。Table 1. 表7.1 文件访问常量 常量 说明 F_OK
指示文件对调用进程可见的标志。这对于确定文件是否存在很有用,但没有说明rwx权限
R_OK
指示文件可以被调用进程读取的标志
W_OK
指示文件可以被调用进程写入的标志
X_OK
指示文件可以被调用进程执行的标志,在 Windows 系统中等效于 fs.constants.F_OK
-
callback:回调函数,使用一个可能的错误参数进行调用。如果检查可访问性失败,则错误参数将是
Error
对象,常见的Error
对象值如表7.2所示。Figure 1. 表7.2 常见Error对象值及说明
|
例如,查看 demo.txt
和 demo1
文件是否存在,示例代码如下:
var fs = require("fs")
//查看demo.txt文件是否存在
fs.access("demo.txt",fs.constants.F_OK, function (err) {
if (err) {
console.log("demo.txt文件不存在");
}
else {
console.log("demo.txt文件存在");
}
});
//查看demo1文件是否存在
fs.access("demo1 ",fs.constants.F_OK, function (err) {
if (err) {
console.log("demo1文件不存在");
}
else {
console.log("demo1文件存在");
}
});
程序运行结果如下:
demo.txt文件存在
demo1文件不存在
上面示例检查文件是否存在,除此之外,还可以检查文件的相关属性。如要检查文件是否可读,可以将上面代码中第 3 行的 fs.constants.F_OK
修改为 fs.constants.R_OK
;而如果要检查文件是否可写,则可以将 fs.constants.F_OK
修改为 fs.constants.W_OK
。另外,access()
方法的 mode
参数也可以同时设置多个值,如果 mode
参数有多个值,中间用 | 分割。例如,检查 demo.txt
文件是否存在且是否可写的代码如下:
var fs = require("fs")
//查看demo.txt文件是否存在且可写
fs.access("demo.txt",fs.constants.F_OK | fs.constants.W_OK, function (err) {
if (err) {
console.log(err)
if(err.code=="ENOENT"){
console.log("demo.txt文件不存在");
}
else if(err.code="EPERM"){
console.log("demo.txt文件存在,但不可写")
}
else{
console.log("未知错误")
}
}
else {
console.log("demo.txt存在,并且可写");
}
});
在项目文件夹中放置一个设置为只读的 demo.txt
文件,然后运行上面代码,可看到运行结果如下:
[Error: EPERM: operation not permitted, access 'D:\Demo\demo.txt'] {
errno: -4048,
code: 'EPERM',
syscall: 'access',
path: 'D:\\Demo\\demo.txt'
}
demo.txt文件存在,但不可写
|
文件读取
fs
模块为读取文件提供了两个方法,即 readFile()
方法和 readFileSync()
方法,二者的区别是,前者为异步读取文件(默认操作),后者为同步读取文件,这两个方法的语法格式如下:
fs.readFile(file,encoding,callback)
fs.readFileSync(file,encoding)
-
file
:文件名。 -
encoding
:文件的编码格式。 -
callback
:回调函数。
例如,下面代码使用 fs
模块的 readFileSync()
方法和 readFile()
方法分别对文件 poems.txt
和 demo.txt
进行同步和异步读取,并显示读取的内容,代码如下:
//引入模块
var fs = require('fs');
//使用readFileSync()方法同步读取文件
var text = fs.readFileSync('poems.txt', 'utf8');
console.log(text);
//使用readFile()方法异步读取文件
fs.readFile('demo.txt', 'utf8', function (error, data) { //读取结果存储在function回调函数的第2个参数data中
console.log(data);
});
poems.txt
和 demo.txt
文件内容如图7.1所示,运行上面代码后的效果如图7.2所示。


|
【例7.1】模拟听歌时的显示歌词效果。(实例位置:资源包\源码\07\01)
在 WebStorm
中创建项目文件夹,在该项目文件夹中添加一个歌词文件 song.txt
,然后创建 js.js
文件,在 js.js
文件中读取歌词文件中的内容,读取时,需要根据音乐播放进度显示对应的歌词,这需要使用正则表达式对歌词文件中的时间点进行解析(解析的格式为 [00:00.00]),以显示对应时间点的歌词内容。代码如下:
//引入模块
var fs = require('fs');
//读取歌词文件
fs.readFile('./song.txt', function(err, data) {
if (err) {
return console.log('歌词文件读取失败');
}
data = data.toString();
var lines = data.split('\n');
//遍历所有行,通过正则表达式匹配对应时间点(时间点的格式为[00:00.00]),并输出对应的歌词
var reg = /\[(\d{2})\:(\d{2})\.(\d{2})\]\s*(.+)/;
for (var i = 0; i < lines.length; i++) {
(function(index) {
var line = lines[index];
var matches = reg.exec(line);
if (matches) {
//获取分
var m = parseFloat(matches[1]);
//获取秒
var s = parseFloat(matches[2]);
//获取毫秒
var ms = parseFloat(matches[3]);
//获取定时器中要输出的内容
var content = matches[4];
//将分+秒+毫秒转换为毫秒
var time = m * 60 * 1000 + s * 1000 + ms;
//使用定时器,让每行内容在指定的时间输出
setTimeout(function() {
console.log(content);
}, time);
}
})(i);
}
});
song.txt
歌词文件格式及内容如图 7.3 所示,程序运行效果如图 7.4 所示。


本实例的 JavaScript 代码中, |
文件写入
文件写入时,有 4 个方法供选择,分别为 writeFile()
方法、writeFileSync()
方法、appendFile()
方法和 appendFileSync()
方法,下面分别进行介绍。
writeFile() 方法和 writeFileSync() 方法
这两个方法分别用来对文件进行异步和同步写入,它们的语法格式如下:
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
-
file
:文件名或文件描述符。 -
data
:写入文件的内容,可以是字符串也可以是缓冲区。 -
options
:可选参数,可以为以下内容。-
encoding
:编码方式,默认值为utf8
,如果data
为缓冲区,则忽略encoding
参数。 -
mode
:文件的模式。默认值为0o666
。 -
flag
:文件系统标志。默认值为w
。 -
signal
:允许中止正在进行的写入文件操作。
-
-
callback
:回调函数。
【例7.2】创建文件并且向文件中写入内容。(实例位置:资源包\源码\07\02)
在 WebStorm
中新建一个项目文件夹,在其中新建一个 poems.txt
文件,该文件中默认写入一首古诗《登鹳雀楼》;然后创建一个 js.js
文件,在 js.js
文件中首先使用 writeFile()
方法以异步方式向 poems.txt
文件中写入古诗 《春夜喜雨》,然后使用 writeFileSync()
方法以同步方式向一个本不存在的 newpeoms.txt
文件中同样写入古诗 《春夜喜雨》。代码如下:
//引入模块
var fs = require('fs');
//声明要写入的内容
var data = ' 春夜喜雨\n\t\t杜甫\n好雨知时节,当春乃发生。\n随风潜入夜,润物细无声。
\n野径云俱黑,江船火独明。\n晓看红湿处,花重锦官城。';
//使用异步方式向poems.txt文件中写入古诗
fs.writeFile('poems.txt', data, 'utf8', function (error) {
if (error) {
throw error;
}
console.log('异步写入文件完成');
});
//使用同步方式向一个本不存在的newpeoms.txt文件中同样写入古诗
fs.writeFileSync('newpoems.txt', data, 'utf8');
console.log('同步写入文件完成!');
运行程序,进入项目文件夹中,可以发现新增了 newpoems.txt
文件,如图7.5所示,这说明使用 writeFileSync
方法向文件中写入内容时,如果文件不存在,系统会自动创建。分别打开 poems.txt
文件和 newpeoms.txt
文件,发现它们的内容都是古诗《春夜喜雨》,如图7.6所示,这说明使用 writeFile
方法向文件中写入内容时,会覆盖掉原有内容。


appendFile() 方法和 appendFileSync() 方法
这两个方法分别向文件异步追加内容和同步追加内容,它们的语法格式如下:
fs.appendFile(path, data[, options],callback)
fs.appendFileSync(path, data[, options])
-
path
:文件路径。 -
data
:要写入文件的数据。 -
callback
:回调函数。 -
options
:可选参数,可以为以下内容。-
encoding
:编码方式,默认值为utf8
。 -
mode
:文件模式,默认值为0o666
。 -
flag
:文件系统标志,默认值为a
。
-
【例7.3】为古诗增加古诗鉴赏内容。(实例位置:资源包\源码\07\03)
在 WebStorm
中创建项目文件夹,然后向项目文件夹中添加一个 poems.txt
文件,该文件的原始内容为古诗《春夜喜雨》,然后创建 js.js
文件,其中使用 appendFile()
方法为 poems.txt
文件中的古诗添加古诗鉴赏内容。代码如下:
var fs = require("fs")
var path = "poems.txt"
var data = "\n古诗鉴赏:这首诗描写细腻、动人。诗的情节从概括的叙述到形象的描绘,由耳闻到目睹,当晚到次晨,结构谨严。用词讲究。颇为难写的夜雨景色,却写得十分耀眼突出,使人从字里行间呼吸到一股令人喜悦的春天气息。"
fs.appendFile(path, data, function (err) {
if (err) {
console.log(err)
}
else {
console.log("内容追加完成")
}
})
poems.txt
文件原始内容如图7.7所示,运行程序后,再次打开 poems.txt
文件,其内容如图7.8所示。


上面两组方法的区别是:第一组方法向文件写入内容,将新的内容替代文件中的原有内容;第二组方法在文件原内容的后面继续追加内容。具体使用时需要根据实际情况来选择方法。 |
文件操作时的异常处理
前面学习了文件读取和写入的操作方法,在实际编程中,经常会出现一些异常情况。比如,读取文件时文件并不存在,或者读取文件时文件路径有误等。出现类似情况会导致程序直接崩溃。所以,无论是异步方法还是同步方法,都需要对这些异常情况进行处理。
同步操作的异常处理
使用同步方法进行文件操作时,可以使用 try-catch
语句进行异常处理。示例代码如下:
//引入模块
var fs = require('fs');
//文件读取
try {
var data = fs.readFileSync('textfile.txt', 'utf8');
console.log(data);
} catch (e) {
console.log(e);
}
//文件写入
try {
fs.writeFileSync('textfile.txt', 'Hello World .. !', 'utf8');
console.log('完成文件写入操作');
} catch (e) {
console.log(e);
}
异步操作的异常处理
使用异步方法进行文件操作时,可以使用 if-else
语句进行异常处理。示例代码如下:
//引入模块
var fs = require('fs');
//文件读取
fs.readFile('textfile.txt', 'utf8', function (error, data) {
if (error) {
console.log(error);
} else {
console.log(data);
}
});
//文件写入
fs.writeFile('textfile.txt', 'Hello World .. !', 'utf8', function (error) {
if (error) {
console.log(error);
} else {
console.log('完成文件写入操作');
}
});