🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[success] # 二进制 1. 在计算机中,很少的情况我们会直接操作一位二进制,因为一位二进制存储的数据是非常有限的,**会将8位合在一起作为一个单元,这个单元称之为一个字节(byte)** **1byte = 8bit,1kb=1024byte,1M=1024kb;** 2. 因此一个自己的表示范围在 `0000 0000 - 1111 1111` 转换十进制的范围也就是 `0- 255`,因此像在css中**RGB**的值分别都是**255**,所以本质上在计算机中都是用**一个字节存储的** 3. 计算机中所有的内容:**文字、数字、图片、音频、视频最终都会使用二进制来表示** * **文字** 编码是将字符映射为不同的二进制值,不同的编码方式对应不同的二进制表示方法,常见 **ASCII编码:** 将每个字符映射到一个唯一的**7位二进制数**。 **UTF-8编码:** 用**1至4个字节**来表示一个字符,其中英文字母和数字占用一个字节,汉字等较复杂字符占用多个字节。 **Unicode编码:** 支持更广泛的字符集,采用的是16位二进制数作为基本单位也就是**两个字节**。 * **图片** 我们需要读取的是一张图片数据(二进制),再通过某些手段对图片数据进行二次的处理(裁剪、格式转换、旋转、添加滤镜) >[success] # Buffer 1. 在 Node.js 中,**Buffer 类是用于处理二进制数据的类**。它是一个**全局对象**,因此无需使用 require() 就可以直接使用。**Buffer 类的实例类似于整数数组**,但是它是**固定大小的,且在内存中分配空间时是以字节为单位的**。 2. `Buffer`中存储的是**二进制数据**但当实际打印`Buffer `时候展示是**16进制**,这是因为实际`Buffer`看成是一个存储二进制的数组,这个数组中的每一项,可以保存8位二进制: `0000 0000` 也就是buffer 数组中一项是**一个字节**,一个字节(8 位)正好 ~~~ const buf2 = Buffer.from('hello world') console.log(buf2) // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64> ~~~ 八个字节可以表示的数字范围在**0 到 255 包括了 256 个不同的取值**,而一个字节(8 位)正好可以表示 256 个不同的取值,在十六进制中,每个数字可以用 4 个二进制位(即 4 个比特)表示。因此,一个字节的取值范围可以用 00~FF 表示,其中 00 表示二进制的 00000000,而 FF 表示二进制的 11111111,所以,**一个字节**的十六进制表示需要 **2 个十六进制数字**,现在再来看案例打印出来的`<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>` 因为是英文所以对应`ascii`码的十六进制表现 `68 =》H` "H" 对应 ASCII 码的十进制表示是 72,十六进制表示是 0x48。依次类推,但中文不是一一对应的关系可以参考下面章节案例 ~~~ const buf = Buffer.from('hello world') // 将 ASCII 编码的 "Hello" 转换为 Buffer 对象 const hexString = buf.toString('hex'); // 获取十六进制字符串表示 let binaryResult = ''; // 用于保存最终的二进制结果 // 将十六进制字符串转换为二进制表示 for (let i = 0; i < hexString.length; i += 2) { const hexChar = hexString.substring(i, i + 2); const intValue = parseInt(hexChar, 16); // 将十六进制字符串解析为整数 const binaryValue = intValue.toString(2).padStart(8, '0'); // 将整数转换为二进制字符串,并补齐至 8 位 binaryResult += binaryValue; } console.log(binaryResult); // 输出二进制表示:0100100001100101011011000110110001101111 ~~~ 分割`0100100001100101011011000110110001101111` =》 其实实际二进制效果`[01001000,01100101,01101100,01101100,01101111 .....]` >[danger] ##### 有一个例子说明 转换过程 ~~~ const buf = Buffer.from('我') console.log(buf) // <Buffer e6 88 91> ~~~ 可以使用JavaScript内置的`TextEncoder`API来将汉字转换成对应的UTF-8字节序列,并将字节序列转换为十六进制格式表示。 以下是一个例子,演示了如何将汉字`我`转换成UTF-8字节序列,并将该序列转换为十六进制格式表示: ~~~ const encoder = new TextEncoder() const sourceString = '我' const encodedString = encoder.encode(sourceString) console.log(`字符串 "${sourceString}" 的UTF-8字节序列为: ${encodedString}`) // encodedString=> Uint8Array(3) [ 230, 136, 145 ] const hexString = encodedString.reduce((acc, byte) => { return acc + byte.toString(16).padStart(2, '0') // 十进制补位 }, '') console.log( `字符串 "${sourceString}" 的UTF-8编码表示为: ${hexString.toUpperCase()}` ) const buf = Buffer.from('我') console.log(buf) // <Buffer e6 88 91> ~~~ 输出: ~~~ 字符串 "我" 的UTF-8字节序列为: Uint8Array [ 230, 136, 145 ] 字符串 "我" 的UTF-8编码表示为: E68891 ~~~ 在这个例子中,我们首先创建了一个`TextEncoder`对象,然后使用`encode`方法将源字符串转换为其对应的UTF-8字节序列。接着,我们遍历这个字节序列,并将每个字节转换为十六进制表示,然后将这些十六进制值拼接在一起,构成最终的UTF-8编码表示。 >[info] ## api | 方法名 | 说明 | 使用方法 | | --- | --- | --- | | Buffer.alloc(size\[, fill\[, encoding\]\]) | 创建并填充一个固定大小且预先分配的Buffer实例 | `const buf = Buffer.alloc(10, 'a')` | | Buffer.allocUnsafe(size) | 创建一个指定大小的未初始化的Buffer实例 | `const buf = Buffer.allocUnsafe(10)` | | Buffer.from(array) | 从一个整数数组中创建一个Buffer实例,数组中应当包含0~255之间的整数 | `const buf = Buffer.from([1, 2, 3])` | | Buffer.from(buffer) | 从一个已有的Buffer实例中创建一个新的Buffer实例 | `const newBuf = Buffer.from(oldBuf)` | | Buffer.from(string\[, encoding\]) | 将一个字符串转换为Buffer实例,第二个参数是可选的,指定字符串编码 | `const buf = Buffer.from('hello')` | | Buffer.byteLength(string\[, encoding\]) | 返回一个字符串的字节长度,第二个参数是可选的,指定字符串编码 | `Buffer.byteLength('good')` | | buf.toString(\[encoding\[, start\[, end\]\]\]) | 将Buffer实例转换为字符串,第一个参数是可选的,指定字符串编码 | `console.log(buf.toString('utf8'))` | | buf.slice(\[start\[, end\]\]) | 返回从指定位置开始到结束的一个新的Buffer实例,起始位置和终止位置参数都是可选的 | `const newBuf = buf.slice(2, 5)` | | buf.copy(target\[, targetStart\[, sourceStart\[, sourceEnd\]\]\]) | 将Buffer实例中的数据复制到另一个Buffer实例中,各参数都是可选的 | `buf.copy(newBuf, 0, 2, 5)` | | buf.compare(target) | 比较当前Buffer实例和另一个Buffer实例的内容,返回一个数值,如果比另一个Buffer实例小,返回-1,相等返回0,大于返回1 | `const result = buf.compare(newBuf)` | | buf.equals(otherBuffer) | 比较当前Buffer实例和另一个Buffer实例的内容是否一致,返回一个布尔值 | `const isEqual = buf.equals(newBuf)` | | buf.indexOf(value\[, byteOffset\]\[, encoding\]) | 搜索当前Buffer实例中是否包含指定的值,返回出现位置的索引,如果没有找到,返回-1。可选的byteOffset参数指定搜索起始位置 | `const index = buf.indexOf('l')` | | buf.includes(value\[, byteOffset\]\[, encoding\]) | 检查当前Buffer实例是否包含指定的值,返回一个布尔值,可选的byteOffset参数指定搜索起始位置 | `const isInclude = buf.includes('h')` | | buf.write(string\[, offset\]\[, length\]\[, encoding\]) | 将一个字符串写入Buffer实例中,返回写入的字节数。可选的offset和length参数指定写入的起始位置和写入的最大长度。如果设置了encoding参数,则将字符串编码为指定的字符集 | `const writtenBytes = buf.write('hello')` | | buf.fill(value\[, offset\[, end\]\]\[, encoding\]) | 将Buffer实例中的字节全部填充为指定值。可选的offset和end参数指定填充的起始位置和结束位置。如果设置了encoding参数,则将值编码为指定的字符集 | `buf.fill(0, 2, 5)` | | buf.toJSON() | 返回当前Buffer实例的JSON表示形式 | `const json = buf.toJSON()` | | buf.byteOffset | 在父Buffer中的偏移量,指定当前Buffer实例相对于父Buffer的偏移量 | `const byteOffset = buf.byteOffset` | | buf.length | 当前Buffer实例的长度 | `const len = buf.length` | | buf.buffer | 返回分配给Buffer实例的内存池 | `const memory = buf.buffer` | >[danger] ##### 是一个类似数字的结果因此也可通过下角标获取值 ~~~ const buf= Buffer.from('123') console.log(buf[0]) // 49 1的ASCII码是49 // 手动对每个字节进行操作 buf[0] = 100 buf[1] = 0x66 console.log(buf) console.log(buf.toString()) buf[2] = 'm'.charCodeAt() console.log(buf) ~~~ >[danger] ##### Buffer.alloc ~~~ const buf = Buffer.alloc(10, 'a') console.log(buf) // <Buffer 61 61 61 61 61 61 61 61 61 61> ~~~ * 没有指定填充 默认是 00 ~~~ const buf1 = Buffer.alloc(10) console.log(buf1) // <Buffer 00 00 00 00 00 00 00 00 00 00> ~~~ >[danger] ##### buf.toString(\[encoding\[, start\[, end\]\]\]) 1. 在我们进行文件读取时候,读取返回的为`buffer` 类型,有时候想让其转换为utf8 打印,可以直接将调用`toString` 方法转换 ~~~ const fs = require('fs') const buf = fs.readFileSync('a.txt') console.log(buf.toString()) // 123 const buffer = Buffer.from('123') console.log(buffer.toString()) // 默认是 utf8 编码123 console.log(buffer.toString('base64')) // 也可以转换别的编码MTIz ~~~ ??? 长度可变