buffer是node的核心模块,开发者可以利用它来处理二进制数据,比如文件流的读写、网络请求数据的处理等。
buffer的api非常多,本文仅挑选 比较常用/容易理解 的api进行讲解,包括buffer实例的创建、比较、连接、拷贝、查找、遍历、类型转换、截取、编码转换等。
new buffer(array)
buffer.alloc(length)
buffer.allocunsafe(length)
buffer.from(array)
验证下:
例子一:buffer.from(array)
例子二:buffer.from(string[, encoding])
通过string创建buffer,跟将buffer转成字符串时,记得编码保持一致,不然会出现乱码,如下所示。
对乱码的分析如下:
例子三:buffer.from(buffer)
创建新的buffer实例,并将buffer的数据拷贝到新的实例子中去。
判断两个buffer实例存储的数据是否相同,如果是,返回true,否则返回false。
同样是对两个buffer实例进行比较,不同的是:
可以指定特定比较的范围(通过start、end指定)
返回值为整数,达标buf、target的大小关系
假设返回值为
<code>0</code>:buf、target大小相同。
<code>1</code>:buf大于target,也就是说buf应该排在target之后。
<code>-1</code>:buf小于target,也就是说buf应该排在target之前。
看例子,官方的例子挺好的,直接贴一下:
跟 <code>buf.compare(target)</code> 大同小异,一般用于排序。直接贴官方例子:
这里稍微研究下buffer.from(array)。下面是官方文档对api的说明,也就是说,每个array的元素对应1个字节(8位),取值从0到255。
allocates a new buffer using an array of octets.
首先看下,传入的元素为数字的场景。下面分别是10进制、8进制、16进制,跟预期中的结果一致。
再看下,传入的元素为字符串的场景。
<code>0</code>开头的字符串,在parseint('062')时,可以解释为62,也可以解释为50(八进制),这里看到采用了第一种解释。
字符串的场景,跟parseint()有没有关系,暂未深入探究,只是这样猜想。todo(找时间研究下)
感兴趣的同学自行探究。
一开始不自觉的会将<code>buffer.from('1')[0]</code>跟<code>"1"</code>划等号,其实<code>"1"</code>对应的编码是49。
这样对比就知道了,编码为1的是个控制字符,表示 start of heading。
备注:个人觉得<code>totallength</code>这个参数挺多余的,从官方文档来看,是处于性能提升的角度考虑。不过内部实现也只是遍历list,将length累加得到totallength,从这点来看,性能优化是几乎可以忽略不计的。
除了上面提到的性能优化,totallength还有两点需要注意。假设list里面所有buffer的长度累加和为length
totallength > length:返回长度为totallength的buffer实例,超出长度的部分填充0。
totallength < length:返回长度为totallength的buffer实例,后面部分舍弃。
使用比较简单,如果忽略后面三个参数,那就是将buf的数据拷贝到target里去,如下所示:
另外三个参数比较直观,直接看官方例子
跟数组的查找差不多,需要注意的是,value可能是string、buffer、integer中的任意类型。
string:如果是字符串,那么encoding就是其对应的编码,默认是utf8。
buffer:如果是buffer实例,那么会将value中的完整数据,跟buf进行对比。
integer:如果是数字,那么value会被当做无符号的8位整数,取值范围是0到255。
另外,可以通过<code>byteoffset</code>来指定起始查找位置。
直接上代码,官方例子妥妥的,耐心看完它基本就理解得差不多了。
将sring写入buf实例,同时返回写入的字节数。
参数如下:
string:写入的字符串。
offset:从buf的第几位开始写入,默认是0。
length:写入多少个字节,默认是 buf.length - offset。
encoding:字符串的编码,默认是utf8。
看个简单例子
用<code>value</code>填充buf,常用于初始化buf。参数说明如下:
value:用来填充的内容,可以是buffer、string或integer。
offset:从第几位开始填充,默认是0。
end:停止填充的位置,默认是 buf.length。
encoding:如果<code>value</code>是string,那么为<code>value</code>的编码,默认是utf8。
例子:
把buf解码成字符串,用法比较直观,看例子
用于对<code>buf</code>进行<code>for...of</code>遍历,直接看例子。
用于截取buf,并返回一个新的buffer实例。需要注意的是,这里返回的buffer实例,指向的仍然是buf的内存地址,所以对新buffer实例的修改,也会影响到buf。
创建、拷贝、截取、转换、查找
buffer、arraybuffer、dataview、typedarray
buffer vs 编码
buffer.from()、buffer.alloc()、buffer.alocunsafe()
buffer vs typedarray
关于buffer内存空间的动态分配
instances of the buffer class are similar to arrays of integers but correspond to fixed-sized, raw memory allocations outside the v8 heap. the size of the buffer is established when it is created and cannot be resized.
unicode对照表
<a href="https://unicode-table.com/cn/#control-character">https://unicode-table.com/cn/#control-character</a>
字符编码笔记:ascii,unicode和utf-8
<a href="http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html">http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html</a>