文件流
流是指数据的流动,数据从一个地方缓慢的流动到一个地方。流是有方向的
流的分类:
- 可读流:Readable 数据从源头流向内存;
- 可写流:Writable 数据从内存流向源头;
- 双工流:Duplex 数据既可以从源头流向内存,又可以从内存流向源头;
文件可读流
fs.craeteReadStream(path,[options])
创建一个文件可读流,用于读取文件内容
参数
path:读取文件路径
options:配置
- ecoding:编码方式,默认为null,读出内容为buffer
- start:起始字节
- end:结束字节
- highWaterMark:每次读取字节数,默认为 64*1024字节
- autoClose:读完后自动关闭,默认值为true
返回值
Readable的子类ReadStream
事件
通过返回值得到的ReadStream的绑定, .on(事件种类,函数)
open
文件打开事件,文件被打开时触发
1 2 3 4 5 6 7 8 9 10 11
| const rs = fs.createReadStream(filename, { encoding: 'utf-8', highWaterMark: 1 })
rs.on('open', () => { console.log('文件被打开了!') })
|
close
文件关闭后触发
文件关闭的两种方法:
- 可读流.close(); 手动关闭
- 文件读完后自动关闭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| test.txt: I am a Chinese!
const rs = fs.createReadStream(filename, { encoding: 'utf-8', highWaterMark: 1 })
rs.on('close', () => { console.log('文件关闭!') })
rs.close();
输出:文件关闭!
|
error
读取文件出现错误
data
读取到一部分数据后触发,注册data后才会开始读取文件,每次读取highWaterMark指定的数量,回调函数中会附带读到的数据。
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
| const fs = require('fs'); const path = require('path');
const filename = path.resolve(__dirname, './test.txt')
const rs = fs.createReadStream(filename, { encoding: 'utf-8', highWaterMark: 1 })
rs.on('data', chunk => { console.log('文件内容:', chunk) })
输出: 文件内容: I 文件内容: 文件内容: a 文件内容: m 文件内容: 文件内容: a 文件内容: 文件内容: C 文件内容: h 文件内容: i 文件内容: n 文件内容: e 文件内容: s 文件内容: e 文件内容: !
|
end
全部数据读取完毕!
rs.pause()
暂停读取,会触发pause事件
rs.resume()
恢复读取,会触发resume事件
文件可写流
fs.craeteWriteStream(path,[options])
参数
path: 路径
options:配置
- flags: 操作文件的方式,w:覆盖文件;a:追加文件;
- ecoding: 编码方式,默认UTF-8
- start:起始字节
- highWaterMark:每次最多写入的字节数
返回值
Writable的子类WriteStream
事件
.on(事件种类,函数)
open
打开文件
error
读取文件出错
close
关闭文件
ws.write(data)
写入一组数据,data:字符串或buffer
返回值为boolean值:
- true:写入通道没有被填满,接下来的数据可以直接写入,无需排队;
- false:写入通道已被填满,接下来的数据将进入写入队列;
当写入队列排满后再清空时,会触发drain事件。
ws.end([data])
需要手动调用;
结束写入,将自动关闭文件;
data是可选的,表示关闭前的最后一次写入内容;
rs.pipe(ws)
将可读流连接到可写流,可解决背压问题;返回值为ws
文件复制
使用pipe
1 2 3 4 5 6 7 8 9 10
| const fs = require('fs'); const path = require('path');
const from = path.resolve(__dirname, './test.png'); const to = path.resolve(__dirname, './testCopy.png');
const rs = fs.createReadStream(from); const ws = fs.createWriteStream(to);
rs.pipe(ws);
|
手写,使用可读流和可写流
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
| const fs = require('fs'); const path = require('path');
const from = path.resolve(__dirname, './test.png'); const to = path.resolve(__dirname, './testCopy.png');
const rs = fs.createReadStream(from); const ws = fs.createWriteStream(to);
rs.on('data', chunk => { const flag = ws.write(chunk); if (!flag) { rs.pause(); } })
ws.on('drain', () => { rs.resume(); })
rs.on('end', () => { ws.end(); console.log('复制完成!'); })
|
使用readFile和writeFile
1 2 3 4 5 6 7 8
| const from = path.resolve(__dirname, './test.png'); const to = path.resolve(__dirname, './testCopy.png');
const fileContent = fs.promises.readFile(from).then(data => { fs.promises.writeFile(to, data).then(() => { console.log('复制完成!'); }); })
|