fs 文件系统
# fs 文件系统
# 1. Node 中的 fs 文件系统
- 在 Node 中有一个文件系统,所谓的文件系统,就是对计算机中的文件进行增删改查等操作。
- 在 NodeJs 中,给我们提供了一个模块,叫做fs模块(文件系统),专门用于操作文件。
- fs模块是 Node 的核心模块,使用的时候,无需下载,直接引入。
// 引入fs模块 var fs = require("fs");
1
2
fs 中的大部分方法都为我们提供了两个版本:
- 同步方法:带
sync
的方法- 同步方法会阻塞程序的执行
- 同步方法通过返回值返回结果
- 异步方法:不带
sync
的方法- 异步方法不会阻塞程序的执行
- 异步方法都是通过回调函数来返回结果的
[!TIP] Nodejs 的一个特点是异步非阻塞,所以学习的都是异步方法。
# 2. fs 文件写入
文件写入有两种方法,一种是 writeFileSync
(同步),另一种是 writeFile
(异步的)。
// 同步方法
fs.writeFileSync(file, data[, options])
// 异步方法
fs.writeFile(file, data[, options], callback)
1
2
3
4
2
3
4
# 2.1 简单文件写入
[!TIP] 简单文件写入方式是一种异步操作,事实上,后面讲的都是异步操作。
语法:
fs.writeFile(file, data[, options], callback(err) => {})
1
file
:要写入的文件路径+文件名+后缀data
:要写入的数据options
:配置对象(可选参数)encoding
:设置文件的编码方式,默认值:utf8
(万国码)mode
:设置文件的操作权限,默认值是:0o666 = 0o222 + 0o444
0o111
:文件可被执行的权限,.exe .msc 几乎不用,linux有自己一套操作方法。0o222
:文件可被写入的权限0o444
:文件可别读取的权限
flag
:打开文件要执行的操作,默认值是'w'
a
:追加w
:写入
callback
:回调函数err
:错误对象
举例:
//引入内置的fs模块
let fs = require('fs')
//调用writeFile方法
fs.writeFile(__dirname+'/demo.txt','kobe,123', {mode: 0o666, flag: 'a'}, err => {
if(err) console.log('文件写入失败', err)
else console.log('文件写入成功')
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
[!TIP] 在Node中有这样一个原则:错误优先。所以有了回调:
err=>{}
。
# 2.2 流式文件写入
流式文件写入适用于一些比较大的文件,可以分多次向文件中写入内容,有效避免内存溢出的问题。
[!TIP] 可以把流式文件写入比作是使用水管从河里往家里运水,流式文件写入首先要创建流(水管),然后要检测流的状态,文件传输完毕,则要关闭流(拿开水管)。
创建一个文件可写流:
fs.createWriteStream(path[, options])
1
参数说明:
path
:要写入文件的路径 + 文件名 + 文件后缀options
:配置对象(可选参数)flags
:打开文件要执行的操作,默认值:w
encoding
:设置文件的编码方式,默认值:utf8
fd
: 文件统一标识符,linux下文件标识符mode
:设置文件的操作权限,默认值是:0o666 = 0o222 + 0o444
autoClose
: 自动关闭文件,默认值:trueemitClose
: 关闭文件,默认值:truestart
: 整数值,写入文件的起始位置(偏移量)
- 返回值:
<fs.WriteStream>
(一个可写流)
文件流写入的过程:
- 创建一个可写流(水管搭建好了)
let ws = fs.createWriteStream(__dirname+ '/demo.txt', {start:10})
1 - 检测流的状态(只要用到了流,就必须监测流的状态)
ws.on('open',function () { console.log('可写流打开了') }) ws.on('close',function () { console.log('可写流关闭了') })
1
2
3
4
5
6 - 使用可写流写入数据
ws.write('美女\n') ws.write('霉女?\n') ws.write('到底是哪一个?\n')
1
2
3 - 关闭可写流(水管不用了,得收起来)
方式一:在 Node 的 v8 版本中,要用end
方法关闭流,否则可能造成数据丢失。方式二:ws.end();
1close
方法关闭流在 Node V8 可能造成数据丢失。ws.close()
1
# 3. 文件读取
文件读取也有两种方法:
// 同步
fs.readFileSync(path[, options])
// 异步
fs.readFile(path[, options], callback)
1
2
3
4
2
3
4
# 3.1 简单文件读取
语法:
fs.readFile(path[, options], callback(arr, data))
1
参数说明:
path
:要读取文件的路径+文件名+后缀options
:配置对象(可选)callback
:回调函数err
:错误对象data
:读取出来的数据
[!TIP] 当文件读入成功,则
err
为null
,data
为读取到的数据。若当文件读入失败,则err
为异常对象,data
为空。
let fs = require('fs')
fs.readFile(__dirname + '/test.mp4', function (err, data) {
if (err) console.log(err)
else console.log(data)
fs.writeFile('../haha.mp4', data, function (err) {
if (err) console.log(err)
else console.log('文件写入成功')
})
})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
为什么读取出来的东西是Buffer? 用户存储的不一定是纯文本。
[!warning] 简单文件写入和简单文件读取,都是一次性把所有要读取或要写入的内容加到内存中,容易造成内存泄露。
# 3.2 流式文件读取
对于一个较大的文件,我们不能通过简单方式读取。因为简单方式是一次性读取,内存可能不够用。这个时候我们可以使用流式读取,分多次读取。
创建一个文件读取流语法:
fs.createReadStream(path[, options])
1
参数说明:
path
:要读取的文件路径 + 文件名 + 后缀options
:可选配置项flags
encoding
fd
mode
autoClose
emitClose
start
:起始偏移量end
:结束偏移量highWaterMark
:每次读取数据的大小,默认值是64 * 1024
(64KB
)
流式读取(并写入到一个新文件中)文件过程:
let { createReadStream, createWriteStream } = require('fs')
//创建一个可读流
let rs = createReadStream(__dirname + '/music.mp3', {
// 10M
highWaterMark: 10 * 1024 * 1024,
// start end 参数一般不用
// start:60000,
// end:120000
})
//创建一个可写流
let ws = createWriteStream('../haha.mp3')
// 只要用到了流,就必须监测流的状态
rs.on('open', function () {
console.log('可读流打开了')
})
rs.on('close', function () {
console.log('可读流关闭了')
// 正确关闭流方式:当没有数据可读,读取流关闭,则写入流也关闭
ws.close()
})
ws.on('open', function () {
console.log('可写流打开了')
})
ws.on('close', function () {
console.log('可写流关闭了')
})
// 给可读流绑定一个data事件,就会触发可读流自动读取内容。
rs.on('data', function (data) {
// Buffer实例的length属性,是表示该Buffer实例占用内存空间的大小
// 输出的是65536,每次读取64KB的内容
console.log(data.length)
ws.write(data)
// ws.close()
//若在此处关闭流,会写入一次,后续数据丢失
})
// ws.close()
//若在此处关闭流,导致无法写入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08