1 Node服务器开发
2 fs模块-文件系统
3 event模块-事件处理
4 认识二进制和buffer
5 Buffer的创建方式
6 Buffer的源码解析
node 的fs模块操作:
这里主要讲node如何进行读取文件,操作文件。服务器该有的操作node都有。
node的fs读取文本文件内容的demo(文件是直接node xxx.js 运行的,不是放到html里面的代码),3中方法(同步方法,普通异步方法(可能回调地狱),promise的异步方法(代码清晰,建议使用))。这里也要注意encoding要设置utf8,否则不会显示文字,只会显示16进制的内容。:
// commonjs const fs = require('fs')// 1.同步读取 // const res1 = fs.readFileSync('./aaa.txt', { // encoding: 'utf8' // }) // console.log(res1)// console.log('后续的代码~')// 2.异步读取: 回调函数 // fs.readFile('./aaa.txt', { // encoding: 'utf8' // }, (err, data) => { // if (err) { // console.log("读取文件错误:", err) // return // }// console.log("读取文件结果:", data) // }) // console.log("后续的代码~")// 3.异步读取: Promise fs.promises.readFile('./aaa.txt', {encoding: 'utf-8' }).then(res => {console.log("获取到结果:", res) }).catch(err => {console.log("发生了错误:", err) })
文件描述符的作用是可以在读出文件和写入文件时使用,而且读取文件信息的方法是必须使用文件描述符才能看见文件内容的。另外提醒有点就是,打开文件使用完成之后一定要有关闭文件的代码,否则文件一直开着浪费性能:
const fs = require('fs')// 打开一个文件 fs.open('./bbb.txt', (err, fd) => {if (err) {console.log("打开文件错误:", err)return}// 1.获取文件描述符console.log(fd)// 2.读取到文件的信息fs.fstat(fd, (err, stats) => {if (err) returnconsole.log(stats)// 3.手动关闭文件fs.close(fd)}) })
node的fs向文件写入内容的demo,当文件不存在的时候会自动创建文件:
这里注意一下flag的作用,(r是读操作),(w是写操作,这个写操作会覆盖先前的内容),(a是进行追加内容的操作)具体看文章后续的ppt内容。
const fs = require('fs')// 1.有一段内容(客户端传递过来http/express/koa) const content = "hello world, my name is coderwhy"// 2.文件的写入操作 fs.writeFile('./ccc.txt', content, {encoding: 'utf8',flag: 'a' }, (err) => {if (err) {console.log("文件写入错误:", err)} else {console.log("文件写入成功")} })
node的fs文件夹的操作,创建文件夹
const fs = require('fs')// 创建文件夹 directory
fs.mkdir('./why', (err) => {console.log(err)
})
node的fs文件夹的操作,读取文件夹底下的文件信息,读取文件夹
const fs = require("fs")// 读取文件夹 // 1.读取文件夹, 获取到文件夹中文件的字符串 // fs.readdir('./why', (err, files) => { // console.log(files) // })// 2.读取文件夹, 获取到文件夹中文件的信息,这里是只针对文件夹层数只有一层或者二层的时候使用 // fs.readdir('./why', { withFileTypes: true }, (err, files) => { // files.forEach(item => { // if (item.isDirectory()) { // console.log("item是一个文件夹:", item.name)// fs.readdir(`./why/${item.name}`, { withFileTypes: true }, (err, files) => { // console.log(files) // }) // } else { // console.log("item是一个文件:", item.name) // } // }) // })// 3.递归的读取文件夹中所有的文件(不包括文件夹) function readDirectory(path) {fs.readdir(path, { withFileTypes: true }, (err, files) => {files.forEach(item => {if (item.isDirectory()) {readDirectory(`${path}/${item.name}`)} else {console.log("获取到文件:", item.name)}})}) } readDirectory('./why')
node的fs文件夹的操作,修改文件夹或者文件的名字:
const fs = require('fs')// 1.对文件夹进行重命名 // fs.rename('./why', './kobe', (err) => { // console.log("重命名结果:", err) // })// 2.对文件重命名 fs.rename('./ccc.txt', './ddd.txt', (err) => {console.log("重命名结果:", err) })
node 的event模块操作:
以后开发时候需要使用类似eventbus的操作的时候就可以使用这里的event的模块了,也可以去下载别人写好的eventbus库。
基本使用,类似于eventbus
// const { HYEventBus } = require('hy-event-store') // const eventBus = new HYEventBus() // eventBus.on('why', () => {})// events模块中的事件总线 const EventEmitter = require('events')// 创建EventEmitter的实例 const emitter = new EventEmitter()// 监听事件 emitter.on('why', () => {console.log('监听why的事件') })// 发射事件 setTimeout(() => {emitter.emit('why') }, 2000);
取消事件监听:
// const { HYEventBus } = require('hy-event-store') // const eventBus = new HYEventBus() // eventBus.on('why', () => {})// events模块中的事件总线 const EventEmitter = require('events')// 创建EventEmitter的实例 const emitter = new EventEmitter()// 监听事件 emitter.on('why', () => {console.log('监听why的事件') })// 发射事件 setTimeout(() => {emitter.emit('why') }, 2000);
传递参数:
// events模块中的事件总线 const EventEmitter = require('events')// 创建EventEmitter的实例 const emitter = new EventEmitter()// 监听事件 function handleWhyFn(name, age, height) {console.log('监听why的事件', name, age, height) } emitter.on('why', handleWhyFn)// 发射事件 setTimeout(() => {emitter.emit('why', "coderwhy", 18, 1.88)// 取消事件监听emitter.off('why', handleWhyFn)setTimeout(() => {emitter.emit('why')}, 1000) }, 2000);
events模块的其他方法一
const EventEmitter = require('events')const ee = new EventEmitter()ee.on("why", () => {}) ee.on("why", () => {}) ee.on("why", () => {})ee.on('kobe', () => {}) ee.on('kobe', () => {})// 1.获取所有监听事件的名称 console.log(ee.eventNames())// 2.获取监听最大的监听个数 console.log(ee.getMaxListeners())// 3.获取某一个事件名称对应的监听器个数 console.log(ee.listenerCount('why'))// 4.获取某一个事件名称对应的监听器函数(数组) console.log(ee.listeners('why'))
05_events模块的其他方法二.js
const EventEmitter = require('events')const ee = new EventEmitter()// ee.on("why", () => { // console.log("on监听why") // })// 1.once: 事件监听只监听一次(第一次发射事件的时候进行监听) ee.once("why", () => {console.log("on监听why") })// 2.prependListener: 将事件监听添加到最前面 ee.prependListener('why', () => {console.log('on监听why2') })ee.emit('why')// 3.移除所有的事件监听 // 不传递参数的情况下, 移除所有事件名称的所有事件监听 // 在传递参数的情况下, 只会移除传递的事件名称的事件监听 ee.removeAllListeners('why')
buffer帮助我们处理二进制数据:
buffer可以对二进制的任何字节进行修改。
Buffer和字符串的转换。
tostring()可以帮助我们把十六进制转为字符串:
const fs = require('fs')// 1.创建Buffer(不建议用这个方法创建了) // const buf = new Buffer('hello') // console.log(buf)// 2.创建Buffer(建议用这里的方法创建) // const buf2 = Buffer.from('world') // console.log(buf2)// 3.创建Buffer(字符串中包含中文) // const buf3 = Buffer.from('你好啊hhhhh') // console.log(buf3) // console.log(buf3.toString())// 4.手动指定的Buffer创建过程的编码 // 编码操作 const buf4 = Buffer.from('哈哈哈', 'utf16le') console.log(buf4) // 解码操作 console.log(buf4.toString('utf16le'))
Buffer的其他创建方式
const fs = require('fs')// 1.创建一个Buffer对象 // 8个字节大小的buffer内存空间 const buf = Buffer.alloc(8) // console.log(buf)// 2.手动对每个字节进行访问 // console.log(buf[0]) // console.log(buf[1])// 3.手动对每个字节进行操作 buf[0] = 100 buf[1] = 0x66 console.log(buf) console.log(buf.toString())buf[2] = 'm'.charCodeAt() console.log(buf)
从文件中读取Buffer:
图片被读取就会显示成二进制文件。
buffer可以操作二进制文件的每一个字节
const fs = require('fs')// 1.从文件中读取buffer // fs.readFile('./aaa.txt', { encoding: 'utf-8' }, (err, data) => { // console.log(data) // })// fs.readFile('./aaa.txt', (err, data) => { // console.log(data.toString()) // })// fs.readFile('./aaa.txt', (err, data) => { // data[0] = 0x6d // console.log(data.toString()) // })// 2.读取一个图片的二进制(node中有一个库sharp) fs.readFile('./kobe02.png', (err, data) => {console.log(data) })