>[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
~~~
??? 长度可变
- 基础
- 什么是Node.js
- 理解 I/O 模型
- 理解node 中 I/O
- 对比node 和java 使用场景
- node 模块管理
- 内置模块 -- buffer
- 内置模块 -- fs
- fs -- 文件描述符
- fs -- 打开文件 api
- fs -- 文件读取 api
- fs -- 文件写入 api
- fs -- 创建目录 api
- fs -- 读取文件目录结构 api
- fs -- 文件状态(信息) api
- fs -- 删除文件/目录 api
- fs -- 重命名 api
- fs -- 复制文件 api
- 内置模块 -- events
- 内置模块 -- stream
- 可读流 -- Readable
- 可写流 -- Writable
- Duplex
- Transform
- 内置模块 -- http
- http -- 从客户端发起
- http -- 从服务端发起
- 内置模块 -- url
- 网络开发