在学习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

  1. let fs = require('fs')
  2. //写入流
  3. let data = 'www.sxt.com'
  4. //1.创建写入流
  5. // --语法:fs.createWriteStream(文件路径,[可选配置操作])
  6. //创建一个可以写入状态的流,写入到文件output.txt中
  7. let wirterStream = fs.createWriteStream('output.txt')
  8. //使用utf-8编码写入数据
  9. wirterStream.write(data,'utf-8')
  10. //标记文件末尾
  11. wirterStream.end();
  12. //处理流事件 --> data,end,and error
  13. wirterStream.on('finish',function(){
  14. console.log('写入完成')
  15. })
  16. wirterStream.on('error',function(err){
  17. console.log(err.stack)
  18. })
  19. console.log('程序执行完毕')

执行:

  1. node main.js

fs.createWriteStream
简写形式:

  1. let fs = require('fs')
  2. let ws = fs.createWriteStream('hello.txt',{flags:'w',encoding:'utf-8'})
  3. console.log(ws)

结果:

  1. WriteStream {
  2. fd: null,
  3. path: 'hello.txt',
  4. flags: 'w',
  5. mode: 438,
  6. ....
  7. }

可以进行事件的监听:

  1. //监听文件打开事件
  2. wx.on('open',function(){
  3. console.log('文件打开')
  4. })
  5. //监听准备事件
  6. wx.on('ready',function(){
  7. console.log('文件写入已准备状态')
  8. })
  9. //写入数据
  10. wx.write("hello world",function(err){
  11. if(err){
  12. console.log(err)
  13. }else{
  14. console.log("内容流入完成")
  15. }
  16. })
  17. //end:表示写入完成
  18. wx.end(function(){
  19. console.log('文件写入关闭')
  20. })
  21. //监听文件关闭事件
  22. wx.on('close',function(){
  23. console.log('文件写入完成关闭')
  24. })

从流中读取数据

读和写很类似
创建input.txt文件:

  1. www.sxt.com

创建main.js文件:

  1. var fs = require('fs')

创建一个可读的流:fs.createReadStream

  1. let readerStream = fs.createReadStream('input.txt')

设置编码为utf-8:

  1. readerStream.setEncoding('utf-8')

输出readStream

  1. //1.首先导入fs模块
  2. let fs = require('fs')
  3. //2.创建读取流,语法:fs.createReadStream(路径,[可选配置项])
  4. let rs = fs.createReadStream('input.txt',{flags:'r',encoding:'utf-8'})
  5. console.log(rs)

结果:

  1. ReadStream {
  2. fd: null,
  3. path: 'input.txt',
  4. flags: 'r',
  5. mode: 438,
  6. start: undefined,
  7. end: Infinity,
  8. pos: undefined,
  9. bytesRead: 0,
  10. ....
  11. }

基础的打开关闭

  1. rs.on('open',function(){
  2. console.log('读取的文件已打开')
  3. })
  4. rs.on('close',function(){
  5. console.log('读取流结束')
  6. })

在这里我们还有专门的一个事件去处理读取:我发一段一段发给你
一点一点小心翼翼的去读取;也是采用了事件去一点一点的去提取

我们的一点一点去提取的监听事件叫data

data可以用来监听我们数据流的:

  1. //每一批数据流入的完成
  2. rs.on('data',function(chunk){
  3. console.log('单批数据流入')
  4. console.log(chunk)
  5. })

小文件看不出大小,但是大文件就可以看出效果

  1. let rs = fs.createReadStream('文件路径',{flags:'r'})
  2. // console.log(rs)
  3. rs.on('open',function(){
  4. console.log('读取的文件已打开')
  5. })
  6. //每一批数据流入的完成
  7. rs.on('data',function(chunk){
  8. console.log('单批数据流入:',chunk.length)
  9. console.log(chunk)
  10. })
  11. rs.on('close',function(){
  12. console.log('读取流结束')
  13. })

输入流配合写入流:

  1. //1.首先导入fs模块
  2. let fs = require('fs')
  3. //2.创建读取流,语法:fs.createReadStream(路径,[可选配置项])
  4. let rs = fs.createReadStream('input.txt',{flags:'r',encoding:'utf-8'})
  5. let ws = fs.createWriteStream('a.txt',{flags:'w',encoding:'utf-8'})//写入;[可选配置项]跟读取一致
  6. // console.log(rs)
  7. rs.on('open',function(){
  8. console.log('读取的文件已打开')
  9. })
  10. //每一批数据流入的完成
  11. rs.on('data',function(chunk){
  12. console.log('单批数据流入:',chunk.length)
  13. console.log(chunk)
  14. ws.write(chunk,()=>{console.log('单批输入流入完成')})//写入
  15. })
  16. rs.on('close',function(){
  17. ws.end
  18. console.log('读取流结束')
  19. })

这个我们可以封装起来

  1. let fs = require('fs')
  2. function myFsWriteStreamTXT(FileName,neiru){
  3. let ws = fs.createWriteStream(FileName,{flags:'w',encoding: 'utf-8'})
  4. ws.on('open',function(){
  5. console.log('写入开始')
  6. })
  7. ws.write(neiru,()=>{console.log('单批输入流入完成')})
  8. ws.on('close',function(){
  9. ws.end()
  10. })
  11. }
  12. function myFsReadStreamTXT(FileName){
  13. let rs = fs.createReadStream(FileName,{flags:'r',encoding:'utf-8'})
  14. rs.on('open',function(){
  15. console.log('读取的文件已打开')
  16. })
  17. rs.on('data',function(data){
  18. console.log('单批数据流入:',data.length)
  19. console.log(data)
  20. })
  21. rs.on('close',function(){
  22. console.log('读取流结束')
  23. })
  24. }
  25. function myFsReadEndWriteStreamTXT(FileName){
  26. let rs = fs.createReadStream(FileName,{flags:'r',encoding:'utf-8'})
  27. rs.on('open',function(){
  28. console.log('读取的文件已打开')
  29. })
  30. rs.on('data',function(data){
  31. console.log('单批数据流入:',data.length)
  32. console.log(data)
  33. myFsWriteStreamTXT(FileName,data)
  34. })
  35. rs.on('close',function(){
  36. console.log('读取流结束')
  37. })
  38. }
  39. module.exports = {myFsWriteStreamTXT,myFsReadStreamTXT,myFsReadEndWriteStreamTXT}

这样还是挺累的,所以它还有一个接口

这个接口可以让你们不用写这么多代码:用管道

管道流(学会输入输出流的原理后,这个就是关键(封装了以上的输入输出流提供给我们))

管道提供了一个输出流到输入流的机制。通过我们用于从一个流中获取数据并将数据传递到另一个流中。
具体如下:

  1. let fs = require('fs')
  2. let rs = fs.createReadStream('input.txt')
  3. let ws = fs.createWriteStream('b.txt')
  4. //管道读写操作
  5. //读取input.txt文件内容,并写入到output中
  6. rs.pipe(ws)

这个管道就是我们刚刚的输入输出流封装而成的一个管道