>[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
- 網絡開發