在学习fs中我们就可以操作我们的读写相关的一些文件
我们读写相关文件的时候,我们可以通过readFile(读)和writeFile(写)里面的某些数据
但是有一天我们读的数据很大的时候,万一我的内存并不能够直接把整个数据全部读取下来
所以我们要读取比较大的数据的时候,我们不可能一次性的把所有的数据都读取出来,这样效率太低了
我们希望的是读一点是一点,所以我们在读写比较大的数据的时候,我们可能需要用到流的这样子的一个接口
Node.js Stream(流)
Stream是一个抽象接口,Node中有很多对象实现了这个接口。例如:对http服务器发起请求的request,对象就是一个Stream,还有stdout(标准输出)
node.js Stream有四种流类型:
- Readable:可读操作
- Writeable:可写操作
- Dupiex:可读可写操作
- Transform:操作被写入数据,然后读出结果
所有的Stream对象都是EventEmitter的实例。常用的事件有: - data:当有数据可读时触发
- end:没有更多的数据可读时触发
- error:在接收和写入过程中发生错误时触发
- finish:所有数据已被写入过程到底层系统时触发
写入流
创建main.js
let fs = require('fs')//写入流let data = 'www.sxt.com'//1.创建写入流// --语法:fs.createWriteStream(文件路径,[可选配置操作])//创建一个可以写入状态的流,写入到文件output.txt中let wirterStream = fs.createWriteStream('output.txt')//使用utf-8编码写入数据wirterStream.write(data,'utf-8')//标记文件末尾wirterStream.end();//处理流事件 --> data,end,and errorwirterStream.on('finish',function(){console.log('写入完成')})wirterStream.on('error',function(err){console.log(err.stack)})console.log('程序执行完毕')
执行:
node main.js
fs.createWriteStream
简写形式:
let fs = require('fs')let ws = fs.createWriteStream('hello.txt',{flags:'w',encoding:'utf-8'})console.log(ws)
结果:
WriteStream {fd: null,path: 'hello.txt',flags: 'w',mode: 438,....}
可以进行事件的监听:
//监听文件打开事件wx.on('open',function(){console.log('文件打开')})//监听准备事件wx.on('ready',function(){console.log('文件写入已准备状态')})//写入数据wx.write("hello world",function(err){if(err){console.log(err)}else{console.log("内容流入完成")}})//end:表示写入完成wx.end(function(){console.log('文件写入关闭')})//监听文件关闭事件wx.on('close',function(){console.log('文件写入完成关闭')})
从流中读取数据
读和写很类似
创建input.txt文件:
www.sxt.com
创建main.js文件:
var fs = require('fs')
创建一个可读的流:fs.createReadStream
let readerStream = fs.createReadStream('input.txt')
设置编码为utf-8:
readerStream.setEncoding('utf-8')
输出readStream
//1.首先导入fs模块let fs = require('fs')//2.创建读取流,语法:fs.createReadStream(路径,[可选配置项])let rs = fs.createReadStream('input.txt',{flags:'r',encoding:'utf-8'})console.log(rs)
结果:
ReadStream {fd: null,path: 'input.txt',flags: 'r',mode: 438,start: undefined,end: Infinity,pos: undefined,bytesRead: 0,....}
基础的打开关闭
rs.on('open',function(){console.log('读取的文件已打开')})rs.on('close',function(){console.log('读取流结束')})
在这里我们还有专门的一个事件去处理读取:我发一段一段发给你
一点一点小心翼翼的去读取;也是采用了事件去一点一点的去提取
我们的一点一点去提取的监听事件叫data
data可以用来监听我们数据流的:
//每一批数据流入的完成rs.on('data',function(chunk){console.log('单批数据流入')console.log(chunk)})
小文件看不出大小,但是大文件就可以看出效果
let rs = fs.createReadStream('文件路径',{flags:'r'})// console.log(rs)rs.on('open',function(){console.log('读取的文件已打开')})//每一批数据流入的完成rs.on('data',function(chunk){console.log('单批数据流入:',chunk.length)console.log(chunk)})rs.on('close',function(){console.log('读取流结束')})
输入流配合写入流:
//1.首先导入fs模块let fs = require('fs')//2.创建读取流,语法:fs.createReadStream(路径,[可选配置项])let rs = fs.createReadStream('input.txt',{flags:'r',encoding:'utf-8'})let ws = fs.createWriteStream('a.txt',{flags:'w',encoding:'utf-8'})//写入;[可选配置项]跟读取一致// console.log(rs)rs.on('open',function(){console.log('读取的文件已打开')})//每一批数据流入的完成rs.on('data',function(chunk){console.log('单批数据流入:',chunk.length)console.log(chunk)ws.write(chunk,()=>{console.log('单批输入流入完成')})//写入})rs.on('close',function(){ws.endconsole.log('读取流结束')})
这个我们可以封装起来
let fs = require('fs')function myFsWriteStreamTXT(FileName,neiru){let ws = fs.createWriteStream(FileName,{flags:'w',encoding: 'utf-8'})ws.on('open',function(){console.log('写入开始')})ws.write(neiru,()=>{console.log('单批输入流入完成')})ws.on('close',function(){ws.end()})}function myFsReadStreamTXT(FileName){let rs = fs.createReadStream(FileName,{flags:'r',encoding:'utf-8'})rs.on('open',function(){console.log('读取的文件已打开')})rs.on('data',function(data){console.log('单批数据流入:',data.length)console.log(data)})rs.on('close',function(){console.log('读取流结束')})}function myFsReadEndWriteStreamTXT(FileName){let rs = fs.createReadStream(FileName,{flags:'r',encoding:'utf-8'})rs.on('open',function(){console.log('读取的文件已打开')})rs.on('data',function(data){console.log('单批数据流入:',data.length)console.log(data)myFsWriteStreamTXT(FileName,data)})rs.on('close',function(){console.log('读取流结束')})}module.exports = {myFsWriteStreamTXT,myFsReadStreamTXT,myFsReadEndWriteStreamTXT}
这样还是挺累的,所以它还有一个接口
这个接口可以让你们不用写这么多代码:用管道
管道流(学会输入输出流的原理后,这个就是关键(封装了以上的输入输出流提供给我们))
管道提供了一个输出流到输入流的机制。通过我们用于从一个流中获取数据并将数据传递到另一个流中。
具体如下:
let fs = require('fs')let rs = fs.createReadStream('input.txt')let ws = fs.createWriteStream('b.txt')//管道读写操作//读取input.txt文件内容,并写入到output中rs.pipe(ws)
这个管道就是我们刚刚的输入输出流封装而成的一个管道
