Structure-study-Node(Buffer、fs)

333 阅读2分钟

编码

Node里面中文采用3个字节来表示,node里默认值支持utf8格式

如何实现base64转换

将一个汉字占的位数 3 * 8 转换为 6 * 4,然后转换为十进制去指定的字符串中查值

    console.log(0xe7.toString(2));
    console.log(0x8f.toString(2));
    console.log(0xa0.toString(2));
    // 11100111  10001111  10100000  3*8 = 6*4
    // 111001  111000  111110  100000
    // base64 转化后去特定的字符串取值
    let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    str+= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toLowerCase();
    str+= '0123456789+/'
    let result = str[0b111001] + str[0b111000] + str[0b111110] + str[0b100000];
    console.log(result);


    // toString 实现
    console.log(Buffer.from('珠').toString('base64'));

Buffer

声明Buffer的方式

1、Buffer.alloc(固定长度)

    let buf = Buffer.alloc(5)
    buf.fill(0)

2、Buffer.from(可以传递数组和字符串)

    let buf = Buffer.from([100,200,120])

    buf = Buffer.from('你好')

buffer常用方法

1、buffer.slice

buffer存放的都是内存地址,如果截取某一段 改变的时候也是更改了这个内存地址

    let buffer = Buffer.from('你好')
    let newBuffer = buffer.slice(0)
    newBuffer[0] = 100
    console.log(buffer)

2、Buffer.isBuffer

判断是不是buffer

    console.log(Buffer.isBuffer(buffer))

3、buffer.copy

    // 代码实现
    Buffer.prototype.copy = function(targetBuffer,targetStart,sourceStart=0,sourceEnd=this.length){
        for(let i = 0;i<sourceEnd-sourceStart,i++){
            targetBuffer[targetStart+i] = this[sourceStart+i]
        }
    }

    // 使用
    let buff = Buffer.alloc(6)
    let buffer1 = Buffer.from('你')
    let buffer2 = Buffer.from('好')

    buffer1.copy(buff,0)
    buffer2.copy(buff,3)
    console.log(buff.toString())

4、Buffer.concat

    Buffer.concat = function(list,length=list.reduce(a,b)=>a+b.length,0){
       let buff = Buffer.alloc(length);
       let offset = 0;
       list.forEach(b=>{
           b.copy(buff,offset)
           offset+=b.length
       });
       return buff
    }

5、buffer.split

扩展方法

    Buffer.prototype.split = function(sep){
        let len = Buffer.from(sep).length;
        let offset = 0;
        let result = []
        let current;
        // 把找到的位置赋给current  看一下是否为-1
        while((current = this.indexOf(sep,offset))!==-1){
            result.push(this.slice(offset,current));// 把每次的记过push到数组中
            offset = current + len // 增加查找偏移量
        }
        result.push(this.slice(offset))// 最后一段追加进去
        return result;
    }

fs

基本API

1、readFile / writeFile

  • 读取文件 文件不存在会报错
  • 写入文件 文件不存在会创建文件 如果有会清空
  • 不适合大文件来使用,否则会导致内存的浪费
    fs.readFile('./note.md',function(err,data){
        fs.writeFile('./node.md1',data,function(){
            
        })
    })

2、open / read / write

  • 手动按照自己来读取 fs.open fs.read fs.write fs.close
  • flag意义
    • r 读取
    • w 写入
    • r+ 在读的基础上可以写 但是文件不存在会报错
    • w+ 在写的基础上读取 如果文件不存在 会创建
    let buffer = Buffer.alloc(3)
    fs.open(path.resolve(__dirname,'./note.md'),'r',(err,rfd)=>{
        fs.open(path.resolve(__dirname,'./note1.md'),'w',(err,wfd)=>{
            // 读取的过程是将读取到的内容 写入到buffer中
            // 写入的文件过程是将buffer中内容读取出来写入到文件中
            fs.read(rfd,buffer,0,3,0,function(err,bytesRead){ // 真正读取到个数
                fs.write(wfd,buffer,0,3,0,function(err){

                })
            });
        })
    })

手动实现读一点,写一点(注意思想 next)

    const fs = require('fs')
    const SIZE = 5
    let buffer = Buffer.alloc(SIZE)
    fs.open('./node.md','r',function(err,rfd){
        fs.open('./copy.md','w',function(err,wfd){
            // 读取的偏移量
            let readOffset = 0
            let writeOffset = 0

            function next(){
                fs.read(rfd,buffer,0,SIZE,readOffset,function(err,bytesRead){
                    // 没有读取到内容  关闭文件
                    if(bytesRead.length === 0){
                        fs.close(wfd,()=>{})
                        return fs.close(rfd,()=>{})
                    }
                })
                fs.write(wfd,buffer,0,bytesRead,writeOffset,function(){
                readOffset +=  bytesRead;
                writeOffset+=bytesRead;
                next()
                })
            }   
            next();
        })
    })