什么問題
如果一個Buffer的 toString()
結果為亂碼或含有亂碼,那么用此字符串以 Buffer.from()
方法構造出來的Buffer將與原來的Buffer不相同。
這一點其實很好理解,只是很多和我一樣的初學者在使用時可能並不會意識到這一點。
用代碼演示的話如下:
let buf = Buffer.from([0x5a,0x6b,0x8c,0x7d,0x9e]);
console.log(buf.toString());
console.log(buf);
let buf1 = Buffer.from(buf.toString());
console.log(buf1);
console.log(buf1.equals(buf));
//運行結果如下
/*
Zk�}�
<Buffer 5a 6b 8c 7d 9e>
<Buffer 5a 6b ef bf bd 7d ef bf bd>
false
*/
怎樣解決
buf.toString()
方法可傳入一個指示編碼格式的參數(參考NodeJS文檔),如果可以通過設置編碼格式使得toString()
方法不發生亂碼則這個問題迎刃而解。其默認值為utf-8.
但是多數情況下我們並不能找到一種合適的編碼格式,比如當buf
是來自一個圖片的二進制數據時,所以最好的方法還是盡量避免這種操作...
補充
Node.js 當前支持的字符編碼如下:
'utf8'
: 多字節編碼的 Unicode 字符。 許多網頁和其他文檔格式都使用 UTF-8。 這是默認的字符編碼。 當將 Buffer 解碼為不專門包含有效 UTF-8 數據的字符串時,則會使用 Unicode 替換字符 U+FFFD � 來表示這些錯誤。'utf16le'
: 多字節編碼的 Unicode 字符。 與 'utf8' 不同,字符串中的每個字符都會使用 2 個或 4 個字節進行編碼。 Node.js 僅支持 UTF-16 的小端序變體。'latin1'
: Latin-1 代表 ISO-8859-1。 此字符編碼僅支持從 U+0000 到 U+00FF 的 Unicode 字符。 每個字符使用單個字節進行編碼。 超出該范圍的字符會被截斷,並映射成該范圍內的字符。'base64'
: Base64 編碼。 當從字符串創建 Buffer 時,此編碼也會正確地接受 RFC 4648 第 5 節中指定的 “URL 和文件名安全字母”。 base64 編碼的字符串中包含的空格字符(例如空格、制表符和換行)會被忽略。'hex'
: 將每個字節編碼成兩個十六進制的字符。 當解碼僅包含有效的十六進制字符的字符串時,可能會發生數據截斷。 請參見下面的示例。'ascii'
: 僅適用於 7 位 ASCII 數據。 當將字符串編碼為 Buffer 時,這等效於使用 'latin1'。 當將 Buffer 解碼為字符串時,則使用此編碼會在解碼為 'latin1' 之前額外取消設置每個字節的最高位。 通常,當在編碼或解碼純 ASCII 文本時,應該沒有理由使用這種編碼,因為 'utf8'(或者,如果已知的數據始終為純 ASCII,則為 'latin1')會是更好的選擇。 這僅為傳統的兼容性而提供。'binary'
: 'latin1' 的別名。 有關此編碼的更多背景,請參閱二進制字符串。 該編碼的名稱可能會引起誤解,因為此處列出的所有編碼都是在字符串和二進制數據之間轉換。 對於在字符串和 Buffer 之間進行轉換,通常 'utf-8' 是正確的選擇。'ucs2'
: 'utf16le' 的別名。 UCS-2 以前是指 UTF-16 的一種變體,該變體不支持代碼點大於 U+FFFF 的字符。 在 Node.js 中,始終支持這些代碼點。
如有錯誤歡迎指正!