一、计算机中的“位”
数据存储的最小单位。在计算机中的二进制数系统中,位,简记为b,也称为比特,每个0或1就是一个位(bit)。计算机中的CPU位数指的是CPU一次能处理的最大位数
二进制数系统中,位简记为b,也称为比特,每个二进制数字0或1就是一个位(bit)。
例如32位计算机的CPU一个机器周期内可以处理32位二进制数据的计算
1位=0.125 字节
1字节等于8位即 1Byte=8bit
128 位(16 个字节 * 8bit)
我们以Rust语言为例子:
let guess: i8 = 255 (0~2^8-1)
//这里的i8表示二进制8位的最大值是11111111
//11111111(二进制) === 255(十进制)
//表示的是这个内存的允许存储的数值大小为0~255之间
//当你存入256给guess这个内存块的时候,程序就有问题了,溢出了。
//当然你比如存的是25数字或者38数字。它们的大小都是2个字节,就是16bit。
//因为英文和数字占一个字节
//
//i32 又叫4字节整数, 因为一个字节等于8比特, 32比特/8=4,占4个字节
//i16 又叫双字节整数
//i8 又叫单字节整数
二、浅谈编码Base64、Hex、UTF-8、Unicode、ASCII码
计算机只认得二进制,0和1,所以我们现在看到的字都是经过二进制数据编码后的。8比特(bit)一个字节,如01011100就是一个字节。英文和数字占一个字节,中文占一个utf-8字符,是两个字节。
补:
buffer底层内容是二进制,但是经常显示是以16进制数组的形式展现出来,不是十六进制的字符串!!
ASE-128-CBC,表示每个加密数据块大小固定为 128 位(16 个字节),而并不是要求你传入的密钥要十六进制字符串。
因此有人会将缓冲区与十六进制字符串混淆。crypto.pbkdfSync(...)返回一个缓冲区,有些人会画蛇添足加上一个crypto.pbkdfSync(...).toString('hex'),这样会改变数据的大小!
Hex编码(base16编码):
Hex编码是十六进制编码,使用16个可见字符来表示一个二进制数组。
Hex编码是一种特殊的字符(刚好2字符表示一个字节)。编码后数据大小将翻倍,具体大小为什么会变化请看base64的原理。
Base64:多种编码沟通的桥梁
base64,意思是使用64个可见字符来表示一个二进制数组,编码后数据大小变成原来的4/3,也即3个字符用4个可见字符来表示。
支持本国语言的编码系统,打开另一个编码系统编码的文本,会出现什么情况呢?这就是乱码了…
位各国互联网通讯间提供一种形式长度也短,效率也高的编码。
原理:
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
关于这个编码的规则:
①把3个字节变成4个字节。
②每76个字符加一个换行符。
③最后的结束符也要处理。
转换前 11111111, 11111111, 11111111 (二进制)
Base64编码转换后 00111111, 00111111, 00111111, 00111111 (二进制)
然后参考base64表:
计算过程:
转换前 10101101,10111010,01110110
转换后 00101011, 00011011 ,00101001 ,00110110
十进制 43 27 41 54 (先转化为十进制!)
对应码表中的值 r b p 2
ASCII码:要让可读性更强
Hex编码、base64编码虽然好,但有个问题:从计算机上打开个文件,满眼的十六进制数,很头大啊… 十六进制还是不太好表示文本。能不能创建一种方法,能表示键盘打出来的全部英文字符、符号呢?键盘打不出来的字符,比如什么回车啦,占位啦,用特殊的符号表示。
ASCII氤氲而生。
Unicode和ASCII的区别
ASCII编码是1个字节,而Unicode编码通常是2个字节。
字母A用ASCII编码是十进制的65,二进制的01000001;而在Unicode中,只需要在前面补0,即为:00000000 01000001。
新的问题:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。
UTF-8:解决除英语之外其他语言
Unicode 当然是一本很厚的字典,记录着世界上所有字符对应的一个数字。UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式。这个编码又称为万国码,顾名思义,就是支持包括中文简体、中文繁体、日语、韩语等各种语言的编码
二、Buffer、ArrayBuffer、TypedArray之间的区别
概述:
ArrayBuffer对象、TypedArray对象、DataView对象是JavaScript操作二进制数据的一个接口。这些对象早就存在,属于独立的规格,ES6将它们纳入了ECMAScript规格,并且增加了新的方法。
这些对象原始的设计目的,与WebGL项目有关。所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。文本格式传递一个32位整数,两端的JavaScript脚本与显卡都要进行格式转化,将非常耗时。这时要是存在一种机制,可以像C语言那样,直接操作字节,将4个字节的32位整数,以二进制形式原封不动地送入显卡,脚本的性能就会大幅提升。
二进制数组就是在这种背景下诞生的。它很像C语言的数组,允许开发者以数组下标的形式,直接操作内存,大大增强了JavaScript处理二进制数据的能力,使得开发者有可能通过JavaScript与操作系统的原生接口进行二进制通信。
1、TypedArray(类型化数组):用来生成内存的类数组视图(view),通过9个构造函数,可以生成9种数据格式的视图,比如Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图, Float32Array(32位浮点数)数组视图等等。
2、ArrayBuffer:代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
3、DataView对象:用来生成内存的视图,可以自定义格式和字节序,比如第一个字节是Uint8(无符号8位整数)、第二个字节是Int16(16位整数)、第三个字节是Float32(32位浮点数)等等。
4、简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray对象代表确定类型的二进制数据,DataView对象代表不确定类型的二进制数据
view视图概念
Buffer 是一个用于操作 ArrayBuffer 的工具(官方称做视图(view))
当我们创建了一个 Buffer 对象后,我们可以通过Buffer对象的 buffer 属性来直接访问其对应的 ArrayBuffer 对象。Buffer.from(arrayBuffer[, byteOffset[, length]])
方法中,你可以传入一个 ArrayBuffer及其视图的位置和长度来创建一个 Buffer 视图,然后去操作它了。
从Node的代码来看,一个 Buffer 对象继承自 Uint8Array,是Uint8Array的子类,大概你可以认为他们相同。
ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图TypedArray视图和DataView视图来代为读写,视图的作用是以指定格式解读二进制数据。
“内存池(memory pool)”是个啥?
结合上面注意:
var buffer = new ArrayBuffer(12); //创建了12个字节的底层二进制ArrayBuffer实例
var x1 = new Int32Array(buffer);
//这里把实例放到了视图构造函数里后生成内存池x1,就可以操作这块内存了
x1[0] = 1; //赋值
var x2 = new Uint8Array(buffer);
x2[0] = 2; //赋值
//结果发现x1内存池和x2内存池是同一个,都是buffer这个12字节大小的实例
//所以切片0的位置也相同,被覆盖赋值了
x1[0] // 2
上面代码对同一段内存,分别建立两种视图:32位带符号整数(Int32Array构造函数)和8位不带符号整数(Uint8Array构造函数)。由于两个视图对应的是同一段内存,一个视图修改底层内存,会影响到另一个视图
总结:Buffer 约等于 Uint8Array 因为 Buffer 就是通过继承 Uint8Array 实现的( Uint8Array 是9种 TypedArray 视图中的一种)。而 ArrayBuffer 是这些内存块,直接存储二进制数据。打个比方,如果说 ArrayBuffer 像是一块标本,而这些视图像是一个显微镜操作台,你可以看(读)到这个 ArrayBuffer 但是你需要这些 TypedArray (或 DataView)视图来操作这些数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。