拾遗之Buffer小知识

447 阅读4分钟

写文章之前先抛出一个问题,写文章属于分享的一种形式,,什么样的东西是需要被分享的?

私以为是新的事物。

那么什么是新的事物?我觉得,一方面对于时间而言,时间上离我们最近,可谓新的事物,我们都学过新闻文体,新闻讲时效性,过了某个时间再发的新闻,就不叫新闻了;另一方面,对于人而言,陌生的东西,让我们产生错觉,觉得是新的,比如说中学学习语文课,老师会说今天教一篇新课文,这篇课文可能是一篇宋词,发生在1000多年前,但是对于学生来说,是新的事物。


所以,今天写的文章,不是什么新鲜事物,只是接触的少,所以觉得是个新事物 -- buffer

buffer这个数据类型对于前端开发者接触还是比较少的,因为前端只需一些简单的字符串操作或dom操作即可满足大部分需求场景,js对字符串操作是比较友好的,但是没有对二进制数据类型进行处理的机制,所以在node中增加了Buffer类对字节流里进行处理。

在《了不起的node.js》,有一段对buffer的定义,我把他摘录如下:

buffer是一个表示固定内存分配的全局对象,它就好比是一个由八位字节元素组成的数组,可以有效地在javascript中表示二进制数据。

我当时读这本书时还是在大学期间,对这句话也是匆匆带过,现在回过头来阅读这段话,发现蕴含了许多当时不懂的知识。现在我们来逐个拆解。

全局对象:node中的全局对象有global对象,process对象,Buffer类,Buffer类是一个全局变量,使用时无需 require('buffer').Buffer。

固定分配:Buffer对象的内存分配不是在v8的堆内存中,而在堆外内存的。每次由node的C++层面负责申请一块固定大小的内存,然后在javascript层面使用它。

八位字节元素的数组:来看看buffer对象的结构,

var str = 'xxx'
var buf = new Buffer(str,'utf-8')
console.log(buf)

=> <Buffer 6e 6f 64 65 e4 bd a0>

计算机通常把8bit作为一个存储单位,称为一个Byte。2的8次方 = 256,范围是0-255。

如果一个1Byte的Buffer,用二进制存储,就是00000001

但是这样显示不太方便,就用了2个16进制来显示,01这种,方便人阅读。

Buffer在文件I/O和网络I/O中效率比字符串高,一旦在网络中传输,都需要转换为Buffer,以二进制数据传输。

一个比较常用的应用场景是对Buffer进行了上层实现。

那么什么是?摘录一段《node学习指南》里一段话:

对不同的socket之间传输的数据称为流。我们可以通过一个buffer对象在流中传送二进制数据,或通过unicode编码方式来传送一个字符串。两种数据最终都会被包装为数据包进行传送。

从这句话大概可以得知流和Buffer的关系,流可以运作在字符串和Buffer上,Buffer用了传二进制数据。

流按类型可以分成4类,按node.js官网文档介绍的,有可读流,可写流,双工流,转换流。

node.js提供了多种流对象,例如文件流、I/O流、http请求、tcp socket、crypto、zlib

流可以通过setEncoding更改数据的编码方式,可以捕捉事件,并为每个事件附加回调函数,可以通过管道把一个可读流与一个可写流连接起来。如下代码,通过事件监听输入,把输入转成大写,然后把输入流跟输出流连接起来。

const Transform = require('stream').Transform
const Readable = require('stream').Readable



let transform1 = Transform({
	transform(chunk,encoding,callback) {
		this.push(chunk.toString().toUpperCase());
		callback();
	}
})


process.stdin.pipe(transform1).pipe(process.stdout)


至此,把流和buffer的相关知识简单介绍完了,更详细的介绍,可以去官网或本文提到的一些书籍中了解,希望看完本文,对你有收获。