当前位置: 首页 > 后端技术 > Node.js

node.js学习记录:了解到Buffer

时间:2023-04-03 23:09:40 Node.js

Buffer是一个类数组对象,存储的是字节,有点类似于字节数组。我们常见的场景是网络请求时处理流数据或者文件操作字符串处理时处理字符。在Node中,应用程序需要处理网络协议、操作数据库、处理图像、接收和上传文件等,在对网络流和文件的操作中,还必须处理大量的二进制数据。JavaScript自身的字符串远远不能满足这些要求(JavaScript字符串存储为utf-8,处理二进制数据的能力较弱,网络层对不同资源的请求响应和文件都是二进制数据进行交互),所以Buffer对象应运而生,nodejs提供了这样一个接口,创建一个专门用于存储二进制数据的缓冲区,并提供一些处理缓冲区数据的方法。Buffer(直译缓冲区,在nodejs中用来处理二进制数据)在nodejs中可以全局访问,不需要用require关键字加载。Buffer和Array一样是一个对象,但主要是用来操作字节的。我们可以发现Buffer是一个对象,也是一个构造函数,有自己的属性和静态方法。newinstance通过它意味着引擎可以分配一块内存,基本上是一个数组,它的元素是十六进制的两位数,也就是0到255之间的值。我们可以从两个方面来理解:模块结构和对象结构层次。模块结构Buffer是一个典型的JavaScript和C++结合的模块。性能相关的部分用C++实现,性能相关的部分用JavaScript实现。Buffer对象1.newBuffer(size):分配一个新的buffer,大小为8位字节大小。2.newBuffer(array):使用8位字节数组分配一个新的缓冲区。3.newBuffer(str,[encoding]):encodingString类型——使用什么编码方式,参数可选。4.类方法:Buffer.isEncoding(encoding):如果给定的encoding编码有效,则返回true,否则返回false。5、类方法:Buffer.isBuffer(obj):测试这个obj是否是一个Buffer。返回布尔值6。类方法:Buffer.concat(list,[totalLength]):list{Array}数组类型,Buffer数组,用于connect。totalLength{Number}type上述Buffer数组中所有Buffer的总大小。>newBuffer('你好晶心的小树屋','base64')Buffer内存分配Buffer对象的内存分配不在V8的堆内存中,而是在Node的C++层面实现内存在Javascript中分配内存的应用程序。为了高效地使用申请的内存,Node使用了slab分配机制。slab是一块已经申请到的固定大小的内存区域。slab有三种状态:full:完全分配状态partial:部分分配状态empty:未分配状态当我们需要一个Buffer对象时,我们可以通过以下方式分配指定大小的Buffer对象newBuffer(size)Node以8KB为boundary来区分Buffer是大对象还是小对象。这个8KB的值就是每个slab的大小值。在JavaScript层面,以它为单位分配内存并写入缓冲区varbuffer=newBuffer(8);//创建一个分配了8字节内存的缓冲区console.log(buffer.write('a','utf8'));//输出1这会将字符“a”写入Buffer,node返回编码后写入buffer的字节数,其中字母a的utf-8编码占1个字节。CopyBufferNode.js提供了一种将Buffer对象的全部内容复制到另一个Buffer对象的方法。我们只能在已经存在的Buffer对象之间进行复制,因此必须创建它们。buffer.copy(bufferToCopyTo)其中,bufferToCopyTo是要复制的目标Buffer对象。下面的例子:varbuffer1=newBuffer(8);buffer1.write('nicetomeetu','utf8');varbuffer2=newBuffer(8);buffer1.copy(buffer2);console.log(buffer2.toString());//nicetomeetu更多信息请看这个https://github.com/ElemeFE/no...ES6TypedArrayBufferconcatvsStringconcat源码=>Warehouseconstfs=require('fs')//从文件创建字节流conststream=fs.createReadStream('test.md',{highWaterMark:11})stream.setEncoding('utf8')vardata=''stream.on('data',function(chunk){data+=chunk})//console.log('dasddd',stream)stream.on('end',function(){console.log(data)})outputinterviewFAQBuffergeneral它用于什么样的数据?它的长度可以动态变化吗?more注意上面的一些API已经被废弃了buffer.allocconstbuf=Buffer.alloc(1024*1024);//分配一块1M内存letoffset=0;//开始编码offset=0;//重置偏移量buf[0]=0;//在开发网络通信协议时,我们应该使用big-endianAPI来操作Buffer,即以BE结尾的。buf.writeInt32BE(1000,1);buf[5]=1;//codec=>1表示JSON序列化偏移+=10;constpayload={service:'com.alipay.nodejs.HelloService:1.0',methodName:'plus',args:[1,2],}constbodyLength=buf.write(JSON.stringfy(payload),offset);buf.writeInt32BE(bodyLength,6);offset+=bodyLength;buf.slice(0,offset);//返回buf.writeInt32BEbuf.writebuf.slice的浅拷贝,类似于Array.slice()创建一个指向与原始Buffer相同的内存的新Buffer,但使用start和end进行修剪。修改新创建的Bufferslice也会同时修改原来的Buffer,因为两个对象分配的内存是重叠的。Buffer.concat/***Buffer的正确拼接**正确的拼接方式是用一个数组存储所有接收到的Buffer分片,并记录所有分片的总长度*然后调用Buffer.concat()方法生成合并缓冲对象。Buffer.concat()方法封装了从小Buffer对象到大Buffer对象的拷贝过程,非常精巧*@list待合并的Buffer数组或Uint8Array数组*@length合并后的Buffer总长度*/Buffer.concat=function(list,length){if(!Array.isArray(list)){thrownewError('Usage:Buffer.concat(list,[length])')}if(list.length===0){returnBuffer.alloc(0)}elseif(list.length===1){returnlist[0]}if(typeoflength!=='number'){length=0for(leti=0;iconstlongBuf=Buffer.from(long.toBytes())Long.fromString('18446744073709551615')//Long{low:-1,high:-1,unsigned:false}有用的packagebuffer的本机API相对较低级别且用户不友好。为了方便使用,社区封装了一些模块:byte常用作buffer操作https://github.com/shelljs/sh...第274行//规范化Buffer的创建,可能的话使用Buffer.alloc。//还为大多数用例提供了良好的默认缓冲区长度。varbuffer=typeofBuffer.alloc==='function'?函数(len){返回Buffer.alloc(len||config.bufLength);}:function(len){returnnewBuffer(len||js基础(二)nodejsDocshttps://github.com/ElemeFE/no...浅谈Node.jsRPC(一)-协议未完待续。。