path 核心模块
- join方法拼接路径,每次拼接都会以上次拼接的结果为基准去拼接
path.join('./a''./b')
path.join('./a','./b','..')
path.join(__dirname,'./a','./b');
复制代码
path.resolve('./a','./b')
=>等价于path.join(__dirname,'./a','./b')
path.resolve('/a')
path.resolve('./a')
复制代码
path.delimiter
复制代码
path.sep
复制代码
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
let fs = require('fs');
let rs = fs.createReadStream('1.txt',{highWaterMark:1})
let arr = []
rs.on('data',chunk=>{
arr.push(chunk);
rs.pause();
setTimeout(()=>{
rs.resume();
},1000)
})
rs.on('end',()=>{
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文件,边读边写。
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')
rs.pipe(ws);
复制代码