当前位置: 首页 > news >正文

20181203-join核心模块方法 + events核心模块发布订阅模式 + fs读写文件流

path 核心模块

  • join方法拼接路径,每次拼接都会以上次拼接的结果为基准去拼接
    path.join('./a''./b') //a/b
    path.join('./a','./b','..') //  /a
    //拼接绝对路径
    path.join(__dirname,'./a','./b'); ///Users/xiaoming/study/20181203/a/b
    
复制代码
  • resolve 解析出绝对路径
    path.resolve('./a','./b') // /Users/xiaoming/study/20181203/a/b
    =>等价于path.join(__dirname,'./a','./b')
    path.resolve('/a')  // /a
    path.resolve('./a')  // /Users/xiaoming/study/20181203/a
复制代码
  • 环境变量分隔符
    path.delimiter // mac: :  windows:;
复制代码
  • 路径分隔符
    path.sep  //mac:/ windows:\
复制代码

events 事件,内置核心模块,发布订阅模式

let EventEmitter = require('events');
let e = new EventEmitter();
/*
e.on(type,fn) //绑定事件
e.once(type,fn)//绑定事件,执行一次就删除
e.emit(type,params)//触发事件
e.removeListener(type,fn)//移除事件的指定订阅者
e.removeAllListener(type)//移除事件所有订阅者
*/
function Girl(){
    
}
let girl = new Girl();
let fn = function(param=""){
    console.log(`${param}哭`)
}
girl.on('失恋',fn)
girl.once('失恋',fn)
girl.on('失恋',(param)=>{console.log(`${param}吃`)})
girl.emit('失恋','我')
girl.removeListener('失恋',fn)
girl.emit('失恋')
girl.removeAllListener('失恋')

//es6手写发布订阅模式
class EventEmitter{
    constructor(){
        this._events = {}
    }
    on(type,cb){
        if(!this._events[type]){
            this._events[type] = [cb]
        }else{
            this._events[type].push(cb)
        }
    }
    emit(type,...args){
        this._events[type].forEach(cb=>{
            cb(...args)
        })
    }
    removeListener(type,fn){
        this._events[type] = this._events[type].filter(cb=>{
            return cb!=fn;
        })
    }
    reveAllListener(type){
        this._events[type] = [];
    }
    once(type,cb){
        let fn = (...args)=>{
            cb(...args)
            this.removeListener(type,fn)
        }
        this.on(type,fn)
    }
}
复制代码

fs读写文件流

流分为可读流和可写流,流是基于事件events的。流可以实现边读边写,读一点写一点,可以控制读文件和写文件的速率,不会出现内存淹没的情况;

通过流可以实现分段读取文件,不关心文件中的内容时可以选择流。 readFile可以看到文件的具体内容

  • 可读流

读取的默认类型是buffer类型,也是内存中;默认每次读取64k

/*
    on('data',(chunk)=>{}) 监听读取事件,由非流动模式变成流动模式,只有监听了才会读出数据
    on('end',()=>{}) 默认的data事件不停的触发,每次读出的chunk,最多就是最高水位线设定的。直到文件中数据全部读完,会触发end事件。
    on('err',()=>{}) //读取出错 或者文件不存在
    rs.pause();读取暂停
    rs.resume();继续读取
*/
let fs = require('fs');
//创建可读流,可设置每次读取多少字节,默认是64*1024字节,64k;
let rs = fs.createReadStream('1.txt',{highWaterMark:1})
let arr = []
//监听读取,由非流动变为流动模式
rs.on('data',chunk=>{
    //读取的默认类型是buffer类型
    arr.push(chunk);
    //暂停读取
    rs.pause();
    //1秒后继续读取
    setTimeout(()=>{
        rs.resume();
    },1000)
})
//监听读取完毕事件
rs.on('end',()=>{
    //buffer拼接
    console.log(Buffer.concat(arr).toString())
})
rs.on('err',()=>{
    console.log('文件不存在| 读取出错')
})

复制代码
  • 可写流

可写流默认每次可写入16*1024字节,16k;页可通过highWaterMark来设置最高每次写入多少;文件如果不存在,在我们创建可写流的时候,就会创建出该文件;可写流写数据,必须是字符串类型或者buffer类型,会叠加内容,不会覆盖

/*
//写文件,write是个异步操作,但是回调一般我们不会用;而且write还有返回值,表示是否已经超过最高水位线,如果是false,表示当前要写的内容超出了最高水位线,一般配合rs.pausep 和 rs.resume完成边读边写。
var flag = ws.write('1',()=>{console.log('写入完成后才会执行')});
//end方法会先把文件写进去;在关闭,调用end后,文件已经关闭就不能在write了。
ws.end('写完了,关闭可写流')

//on('drain',()=>{})写入flag变为false表示写入的东西超过最高水位线;当全部写入进去后,就会触发drain事件,表示此时可以在继续写入。
*/
let fs = require('fs')
//创建可写流
let ws = fs.createWriteStream('2.txt',{highWaterMark:3});
var flag = ws.write('1');
console.log(flag) //true
 var flag = ws.write('1');
 console.log(flag) //true
  var flag = ws.write('1');
 console.log(flag) //false //write是异步的,写完这次后,就超过了最高水位;
 
//ws.end('写完了,关闭')// 尽管write是异步,但end调用后会把所有write中的内容以最快的速度写入文件。所以监听drain事件,不能调用end

//当读入的文件全部写入后,就恢复读取,flag变为false表示写入的东西超过最高水位线;当全部写入进去后,就会触发drain事件,此时可以在继续写入。
ws.on('drain',()=>{
    console.log(‘吃完了')
})
 
复制代码
  • js手动写出pipe方法,完成基于流的copy文件,边读边写。

//拷贝文件 30b文件 读取4b,读取8次 读取第一次就开始写,每次只能写1b,暂停读取,当调用drain后,在恢复读取。
    let fs = require('fs');
    fuction pipe(source,target,cb){
        let rs = fs.createReadStream(source,{highWaterMark:4})
        let ws = fs.createWriteStream(target,{highWaterMark:1});
        rs.on('data',(chunk)=>{
            let flag = ws.write(chunk);
            if(!flag){ //可写流超出最高水位线,暂停读取
                rs.pause();
            }
        })
        ws.on('drain',()=>{
            rs.resume();//当前读出的内容已经全部写入到文件中,调用继续读取。
        })
        rs.on('end',()=>{//当读取完毕,强制将内存中未写完的内容写到文件中,关闭文件。
            ws.end();
        })
    }
    pipe('1.txt','2.txt')
    
    
//可读流提供了方法,可copy到可写流中。
rs.pipe(ws);//会自动调用write 和end方法。
    
复制代码

相关文章:

  • AWS实战 - 利用IAM对S3做访问控制
  • 糟糕的软件设计:幻想出来的问题
  • windows下启动和运行分布式消息中间件消息队列 kafka
  • 关系与外键约束
  • TP自动生成模块目录
  • maven私服搭建
  • canvas 使用图片跨域问题
  • MySQL的安装与配置
  • redhat7.5在H3C机器上黑屏无显
  • 超级详细使用Webpack4.X 搭建H5开发环境
  • 真数组与伪数组的区别
  • 搜狗地图下载|搜狗地图app下载
  • 腾讯朱华:数据中心下一个风向的探索
  • 汇编语言实验9
  • CentOS 7下mysqld服务启动失败终极解决方案
  • [笔记] php常见简单功能及函数
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • ECS应用管理最佳实践
  • java正则表式的使用
  • jquery cookie
  • KMP算法及优化
  • Laravel 中的一个后期静态绑定
  • MySQL用户中的%到底包不包括localhost?
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • scala基础语法(二)
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Spark RDD学习: aggregate函数
  • vue数据传递--我有特殊的实现技巧
  • windows下如何用phpstorm同步测试服务器
  • 分享几个不错的工具
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 一些css基础学习笔记
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • $(selector).each()和$.each()的区别
  • (23)Linux的软硬连接
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (六)vue-router+UI组件库
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)Linux下编译安装log4cxx
  • .bat批处理(六):替换字符串中匹配的子串
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .net refrector
  • .NET Standard 的管理策略
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET开发不可不知、不可不用的辅助类(一)
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [bzoj4240] 有趣的家庭菜园
  • [BZOJ5250][九省联考2018]秘密袭击(DP)
  • [java基础揉碎]关系运算符(比较运算符)逻辑运算符赋值运算符三元运算符运算符的优先级
  • [openGL]在ubuntu20.06上搭建openGL环境