首页 > 编程语言 >Nodejs中流的操作,实现简单的pipe

Nodejs中流的操作,实现简单的pipe

时间:2023-04-26 14:57:48浏览次数:46  
标签:function fs 中流 读取 rs Nodejs 写入 pipe ws

fs与流都可以处理文件,为什么还要用流? fs模块处理文件的缺点:将文件的数据全读到内存中,在把数据写到文件内,会大量占用内存。

流介绍:

        流(stream)是 Node.js 中处理流式数据的抽象接口,是一组有序的,有起点和终点的字节数据传输手段。可以实现将数据从一个地方流动到另一个地方,其边读取边写入的特点有别于fs模块的文件处理,并且可以做到控制读取文件和写入文件的速度,从而减少内存的占用         nodeJS中提供了许多种流的对象,像用http模块创建的服务器的回调内,req就是一个可读流,res就是可写流 流的特点:   1、边读  边写,是边读边写的,读取一段文件,就将它写入   2、流是基于事件的,所有的流对象都用 on绑定事件,并触发

Node.js 中有四种基本的流类型:

可读流:

let fs = require('fs')
//参数1:要读取的文件
//参数2:配置项,有highWaterMark  每次能读取多少,默认是64k,一次读取64k 不需要更改
let rs = fs.createReadStream('1.txt', {     // 返回了一个可读流的实例
    flags: 'r'        //对文件进行何种操作
        encoding: 'utf-8'        //设置之后,读取的是字符串,不然默认为buffer
        start:3                    //从索引3开始读
        end:7                    // 读到索引为7的  包括结束
        highWaterMark: 1
})       

// 默认是不会把读取的文件给你 需要监听事件,数据到来的事件  rs.emit('data',数据);
// 所以把那个绑定这个事件
fs.on('data',function(chunk){
    console,log(chunk)
})
// 默认这个data事件不停的触发,直到文件中的数据全部读完
rs.on('end', function () {
    
})

如果每次读取多少需要自己设置highWaterMark ,读取文件的时候为了不乱码,需要用到buffer拼接转化

let rs = fs,createReadStream('1.txt', {highWaterMark: 1})
let arr = []
rs.on('data',function(chunk){
    arr.push(chunk)            //读取文件时,是buffer类型,将每次读取的buffer拼到一个数组内
    
})
// 当文件全部读完,触发end
res.end('end',function(){
    let filesData = Buffer.concat(arr).toString()
})

//报错是  触发err        文件不存在,会触发这个事件
rs.on('err', function(err){

})

如果想要控制读取的速度,可以用rs.pause() 暂停data事件的触发,  rs.resume() 恢复data事件的触发

let arr = []
rs.on('data',function(chunk){
    arr.push(chunk)
    rs.pause()    //暂停
    setTimeout(()=>{
        rs.resume       //一秒恢复一次  data事件的触发,直到数据读完
    },1000)
})

rs.on('end', ()=>{
    console.log(Buffer.concat(arr).toString())
})

可写流:

1、当往可写流里写数据的时候,不会立刻写入文件,先写入缓存区,缓存区的大小就是highWaterMark,默认为16k 等缓存区满了之后,再次真正的写入文件里 2、通过判断ws.write的返回值判断缓存区是否已经满了。为true是,还没满,有空间,可以继续写,为false时,表示满了 3、按理说如果返回false,就不能再往里写了,但是如果写了,不会丢失,会先缓存在内存中,等缓冲区写完清空之后,在从内存中读取写入。 所以一般在读取文件写入的时候。当缓存区满了,一般会暂停可读流的读取  data事件,等写完之后再次出发可读流的data读取文件,所以不会占用太多的内存
const fs = require('fs')
//第一个参数,写入的文件位置  名称
// 第二参数,配置项
let ws = fs.createWriteStream('./a.txt', {
      flags:'w'
      highWaterMark:2 
})
var flag = ws.write('1', function(){})        //flag为true
//write   写的内容,必须是 字符串或者buffer,
// 会返回一个布尔值,提示是否还有空间写入, 与highWaterMark对应,例如为写入1时,第一次写 返回一个true,表示还有空间写入
//write是异步的 有回调函数,但是不常用
var flag = ws.write('2', function(){})       //flag为false
var flag = ws.write('3', function(){}) 
// 当数据写入文件后,又有空间继续写入时,触发drain事件
ws.on('drain',function(){
    
})
// 当所有文件写完之后,触发end,也可以在end时,在写入最后的数据
ws.end('结束写入')
利用可读流可写流,实现一个pipe,边读边写,控制读取可写入的速度: 读取30b的文件,每次只能读5b,每次只能写入1b 1、可读流第一次读取5b 2、可写流写入读取流读取的数据,拿到5b开始写,因为设置了highWaterMark为1,写了1b之后,ws.write()就返回fasle。 表示没有空间在写入了,剩下的4b放到内存中,开始1b  1b的写入 3、ws.write()返回false后,暂停可读流 的 data事件,等待5b全部写入 4、 5b写完后,触发ws.on('drain',function(){rs.resume()}),    恢复可读流的 data事件,再次读取了5b 5、直到文件读完,写完
const fs = require('fs')

function pipe(readFile,writeFileu){
    let rs = fs.createReadStream(readFile,{
        highWaterMark:5
    })
    let ws = fs.createWriteStream(writeFileu,{
        highWaterMark:1
    })
    rs.on('data',function(chunk){
        console.log('读取')
        // 当ws.write() 返回false时,表示没有空间继续写入了,暂停读取
        if(ws.write(chunk) == false){
            rs.pause() // 暂停rs的data事件
        }
    })
    // 当触发可写流的drain,表示有空间继续写入了,继续读取文件
    ws.on('drain',function(){
        rs.resume() // 恢复rs的data事件        // 把当前读入的内容都写到文件中了,继续调用读写
    })
    // 当读取流触发end方法,表示读取完毕,这时关闭可写流的写入
    rs.on('end',function(){
        ws.end()
    })
}
pipe('1.txt','./2.txt')

 

如果对stream不熟悉,推荐阅读下面文章。

 

标签:function,fs,中流,读取,rs,Nodejs,写入,pipe,ws
From: https://www.cnblogs.com/sttchengfei/p/17356051.html

相关文章

  • 进程间的通信方式——pipe(1、管道)
    本章内容采用pipe管道如何进行进程之间的通信pipe管道进程通信的规则和限制Linux中pipe管道的实现机制和管理pipe管道的结构体什么是进程通信进程通信就是两个进程之间进行数据交换,在Linux中有好几种可以进行进程通信的方式,在这篇文章中我们主要介绍最基本的进程通信方式——pipe管......
  • window操作系统安装多个版本nodejs版本-控制工具nvm
    参考:https://blog.csdn.net/m0_38134431/article/details/118388297https://juejin.cn/post/7044890876631318564电脑上已经安装了10.x版本的nodejs,你不想直接更新到12.x,想同时保存10.x和12.x版本,在必要的时候还能随时切换nodejs版本,nvm工具可以实现一、首先要安装nvm下载地......
  • 记录一次nodejs操作mongodb报错
    记录一次使用Mongoose操作mongodb报错Mongoose查询回调函数报错BookModel.findOne({name:'Rust'},(err,data)=>{if(err){console.log('读取失败');return;}//输出data变量的值console.log(data);......
  • [MLIR] CodeGen Pipeline总结
    参考资料:[MLIR]CodeGenPipeline总结-知乎(zhihu.com)本文主要以tensorflow为例,介绍了其接入MLIR后的CodeGen过程,以及简要分析了一些现在常用的CodeGenpipeline。本文是本人在结合博客(CodegenDialectOverview-MLIR-LLVMDiscussionForums)以及相关资料而写......
  • redis之哈希类型-列表类型-集合类型-有序集合-慢查询-pipeline-发布订阅-Bitmap位图-H
    目录redis之哈希类型-列表类型-集合类型-有序集合-慢查询-pipeline-发布订阅-Bitmap位图-HyperLogLog-GEO地理位置昨日内容回顾今日内容详细1哈希类型2列表类型3集合类型4有序集合5慢查询6pipeline与事务7发布订阅8Bitmap位图9HyperLogLog10GEO地理位置redis之哈希类型......
  • 哈希类型 列表类型 集合类型 有序集合 慢查询 pipeline与事务 发布订阅 Bitmap位图 Hy
    昨日回顾#1redis介绍 -特性#速度快:10wops(每秒10w读写),数据存在内存中,c语言实现,单线程模型#持久化:rdb和aof#多种数据结构:5大数据结构BitMaps位图:布隆过滤器本质是字符串HyperLogLog:超小内存唯一值计数,12kbHyperLogLog本质是......
  • nodejs从命令行获取参数
    //添加参数letarr=process.argv;constconfig={src:"",//添加参数};for(leti=2,len=arr.length;i<len;i+=2)config[arr[i].substring(1)]=arr[i+1];constpara=Object.keys(config).find((e)=>{return!config[e];});i......
  • 使用pipeline执行命令遇到redis.Nil的坑
    参考项目kratos_rockscacheredis数据准备关键代码特别注意,使用pipeline的Exec方法,一定要判断一下redis.Nil这个错误:~~~......
  • windows11 nvm 切换nodejs版本失败
    在windows11,当切换分支命令nvmuse16.15.0显示成功,但用nvmls看的时候发现分支没有切换,可以直接用windows的命令来覆盖原来nodejs文件夹的快捷方式  把这个文件夹删掉,然后用命令重建mklink/dD:\Soft\nvm\nodejsD:\Soft\nvm\nvm\v16.15.0 这样就可以重新指......
  • ubuntu 22.04 安装最新版本的 nodejs
    参考资料:HowToInstallNode.jsonUbuntu20.04采用其中的第二个方法:cd~curl-sLhttps://deb.nodesource.com/setup_18.x-o/tmp/nodesource_setup.shvi/tmp/nodesource_setup.shsudobash/tmp/nodesource_setup.shsudoaptinstallnodejs注意,sudoaptinstallno......