純粹的JavaScript是 Unicode 友好的,但是不能很好地處理二進制數(shù)據(jù)。當處理 TCP 流或者文件流時,操作八進制流是必要的。io.js提供了多種策略來操作,創(chuàng)建和使用八進制流。
原始的數(shù)據(jù)被存儲在Buffer類的實例中,一個Buffer類似于一個整數(shù)數(shù)組但是使用了 V8 堆之外的內(nèi)存分配。一個Buffer不能被改變大小。
Buffer類是全局的,所以它是少數(shù)的不用require('buffer')就能使用的對象之一。
Buffer和JavaScript字符串對象之間的轉(zhuǎn)換需要指定一個明確地編碼方法。以下是一些不同的字符串編碼。
'ascii' - 僅供7位的 ASCII 數(shù)據(jù)使用,這個編碼方法非常的快速,而且會剝離過高的位(如果有設(shè)置)。
'utf8' - 多字節(jié)編碼的字符。許多 web 頁面和一些其他文檔都使用 UTF-8 編碼。
'utf16le' - 2或4個字節(jié),little endian編碼字符。支持(U+10000 到 U+10FFFF)的代理對。
'ucs2' - 'utf16le'的別名。
'base64' - Base64 字符串編碼。
'binary' - 一種通過使用每個字符的前八位來將二進制數(shù)據(jù)解碼為字符串的方式。這個編碼方法已經(jīng)不被推薦使用,在處理Buffer對象時應避免使用它,這個編碼將會在io.js的未來版本中移除。
'hex' - 把每個字節(jié)編碼成2個十六進制字符。
從一個Buffer創(chuàng)建一個類型數(shù)組(typed array)遵循以下的說明:
1,Buffer的內(nèi)存是被復制的,不是共享的。
2,Buffer的內(nèi)存被解釋當做一個數(shù)組,而不是一個字節(jié)數(shù)組(byte array)。換言之,new Uint32Array(new Buffer([1,2,3,4]))創(chuàng)建了一個4個元素([1,2,3,4])的Uint32Array,不是一個只有一個元素([0x1020304] 或 [0x4030201])的Uint32Array。
注意: Node.js v0.8 只是簡單得在array.buffer中保留了buffer的引用,而不是復制一份。
Buffer 類是一個全局類用于直接處理二進制數(shù)據(jù)。它的實例可以被多種途徑構(gòu)建。
分配一個大小為指定size的八位字節(jié)的新buffer。注意,size不能超過 kMaxLength,否則一個RangeError將會被拋出。
使用一個八進制數(shù)組分配一個新的buffer。
將傳遞的buffer復制進一個新的 Buffer 實例。
根據(jù)給定的str創(chuàng)建一個新的buffer,編碼默認是 UTF-8。
true若此編碼是合法的,否則返回false。測試obj是否為一個buffer。
給出string的實際字節(jié)長度。編碼默認為 UTF-8。這與String.prototype.length不同,因為String.prototype.length只返回字符串中字符的數(shù)量。
例子:
str = '\u00bd + \u00bc = \u00be';
console.log(str + ": " + str.length + " characters, " +
Buffer.byteLength(str, 'utf8') + " bytes");
// ? + ? = ?: 9 characters, 12 bytes
若list為空,或totalLength為0,那么將返回一個長度為0的 buffer。
若list只有一個元素,那么這個元素將被返回。
若list有超過一個元素,那么將創(chuàng)建一個新的 Buffer 實例。
如果totalLength沒有被提供,那么將會從list中計算讀取。但是,這增加了函數(shù)的一個額外的循環(huán),所以如果直接長度那么性能會更好。
var arr = [Buffer('1234'), Buffer('0123')];
arr.sort(Buffer.compare);buf = new Buffer(1234);
console.log(buf.length);
buf.write("some string", 0, "ascii");
console.log(buf.length);
// 1234
// 1234
雖然buffer的length屬性并不是不可變的,改變length屬性的值可能會使之變成undefined或引起一些不一致的行為。希望去改變buffer的length的應用應當把它視作一個只讀的值,并且使用buf.slice來創(chuàng)建一個新的buffer。
buf = new Buffer(10);
buf.write("abcdefghj", 0, "ascii");
console.log(buf.length); // 10
buf = buf.slice(0,5);
console.log(buf.length); // 5
buffer.length - offset從指定的偏移位置(offset)使用給定的編碼向 buffer 中寫入字符串,偏移位置默認為0,編碼默認為UTF8。長度為將要寫入的字符串的字節(jié)大小。返回被寫入的八進制流的大小。如果 buffer 沒有足夠的空間寫入整個字符串,那么它將只會寫入一部分。length參數(shù)默認為buffer.length - offset,這個方法將不會只寫入字符的一部分。
buf = new Buffer(256);
len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(len + " bytes: " + buf.toString('utf8', 0, len));
0 <= offset <= buf.length0 < byteLength <= 6false根據(jù)指定的偏移位置(offset)和byteLength將value寫入 buffer。最高支持48位的精確度。例子:
var b = new Buffer(6);
b.writeUIntBE(0x1234567890ab, 0, 6);
// <Buffer 12 34 56 78 90 ab>
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,默認為false。
0 <= offset <= buf.length0 < byteLength <= 6false一個普遍的用來作數(shù)值讀取的方法,最高支持48位的精確度。例子:
var b = new Buffer(6);
b.writeUint16LE(0x90ab, 0);
b.writeUInt32LE(0x12345678, 2);
b.readUIntLE(0, 6).toString(16); // Specify 6 bytes (48 bits)
// output: '1234567890ab'
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
buffer.length從編碼的 buffer 數(shù)據(jù)中使用指定的編碼解碼并返回結(jié)果字符串。如果encoding為undefined或null,那么encoding將默認為 UTF8。start和end參數(shù)默認為0和buffer.length。
buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; // 97 is ASCII a
}
buf.toString('ascii'); // outputs: abcdefghijklmnopqrstuvwxyz
buf.toString('ascii',0,5); // outputs: abcde
buf.toString('utf8',0,5); // outputs: abcde
buf.toString(undefined,0,5); // encoding defaults to 'utf8', outputs abcde
返回一個 Buffer 實例的 JSON 形式。JSON.stringify被隱式得調(diào)用當轉(zhuǎn)換 Buffer 實例時。
例子:
var buf = new Buffer('test');
var json = JSON.stringify(buf);
console.log(json);
// '{"type":"Buffer","data":[116,101,115,116]}'
var copy = JSON.parse(json, function(key, value) {
return value && value.type === 'Buffer'
? new Buffer(value.data)
: value;
});
console.log(copy);
// <Buffer 74 65 73 74>
獲取或設(shè)置指定位置的八位字節(jié)。這個值是指單個字節(jié),所有合法范圍在0x00到0xFF 或 0 到 255。
例子:復制一個 ASCII 字符串到一個 buffer,一次一個字節(jié):
str = "io.js";
buf = new Buffer(str.length);
for (var i = 0; i < str.length ; i++) {
buf[i] = str.charCodeAt(i);
}
console.log(buf);
// io.js
返回一個布爾值表示是否buf與otherBuffer具有相同的字節(jié)。
返回一個數(shù)字表示在排序上buf在otherBuffer之前,之后或相同。
buffer.length從buf中的指定范圍復制數(shù)據(jù)到targetBuffer中的指定范圍,它們是可以重疊的。
例子:創(chuàng)建兩個 Buffer,然后復制 buf1 的第16字節(jié)到19字節(jié)到 buf2,buf2 的偏移位置從第8字節(jié)開始:
buf1 = new Buffer(26);
buf2 = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf1[i] = i + 97; // 97 is ASCII a
buf2[i] = 33; // ASCII !
}
buf1.copy(buf2, 8, 16, 20);
console.log(buf2.toString('ascii', 0, 25));
// !!!!!!!!qrst!!!!!!!!!!!!!
例子: 創(chuàng)建一個單獨的 Buffer,然后復制數(shù)據(jù)到自身的一個重疊的范圍。
buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; // 97 is ASCII a
}
buf.copy(buf, 0, 4, 10);
console.log(buf.toString());
// efghijghijklmnopqrstuvwxyz
buffer.lengthstart和end參數(shù)所偏移和裁剪。修改這個新的 buffer 的切片,也會改變內(nèi)存中原來的 buffer。
例子: 創(chuàng)建一個 ASCII 字母的 Buffer,然后對其進行slice,然后修改源 Buffer 上的一個字節(jié):
var buf1 = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf1[i] = i + 97; // 97 is ASCII a
}
var buf2 = buf1.slice(0, 3);
console.log(buf2.toString('ascii', 0, buf2.length));
buf1[0] = 33;
console.log(buf2.toString('ascii', 0, buf2.length));
// abc
// !bc
行為和 Array.indexOf()相似。接受一個字符串,Buffer 或數(shù)字。字符串被解釋為 UTF8 編碼,Buffer 將使用整個 buffer,所以如果要比較部分的 Buffer 請使用Buffer.slice(),數(shù)字的范圍需在0到255之間。
false根據(jù)制定偏移量從 buffer 中讀取一個無符號8位整數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
例子:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
for (ii = 0; ii < buf.length; ii++) {
console.log(buf.readUInt8(ii));
}
// 0x3
// 0x4
// 0x23
// 0x42
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個無符號16位整數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
例子:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
console.log(buf.readUInt16BE(0));
console.log(buf.readUInt16LE(0));
console.log(buf.readUInt16BE(1));
console.log(buf.readUInt16LE(1));
console.log(buf.readUInt16BE(2));
console.log(buf.readUInt16LE(2));
// 0x0304
// 0x0403
// 0x0423
// 0x2304
// 0x2342
// 0x4223
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個無符號32位整數(shù)。
將noAssert設(shè)置為true將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
例子:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
console.log(buf.readUInt32BE(0));
console.log(buf.readUInt32LE(0));
// 0x03042342
// 0x42230403
false根據(jù)制定偏移量從 buffer 中讀取一個有符號8位整數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
運作和buffer.readUInt8相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個有符號16位整數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
運作和buffer.readUInt16相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個有符號32位整數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
運作和buffer.readUInt32相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個32位浮點數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
例子:
var buf = new Buffer(4);
buf[0] = 0x00;
buf[1] = 0x00;
buf[2] = 0x80;
buf[3] = 0x3f;
console.log(buf.readFloatLE(0));
// 0x01
false根據(jù)制定偏移量從 buffer 中根據(jù)特定的endian字節(jié)序讀取一個64位雙精度數(shù)。
將noAssert設(shè)置為 true 將會跳過value和offset的檢驗,這意味著offset將可能超過buffer 的結(jié)束位置,默認為false。
例子:
var buf = new Buffer(8);
buf[0] = 0x55;
buf[1] = 0x55;
buf[2] = 0x55;
buf[3] = 0x55;
buf[4] = 0x55;
buf[5] = 0x55;
buf[6] = 0xd5;
buf[7] = 0x3f;
console.log(buf.readDoubleLE(0));
// 0.3333333333333333
false向buffer的指定偏移位置寫入value。
注意,value必須是一個合法的無符號8位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
例子:
var buf = new Buffer(4);
buf.writeUInt8(0x3, 0);
buf.writeUInt8(0x4, 1);
buf.writeUInt8(0x23, 2);
buf.writeUInt8(0x42, 3);
console.log(buf);
// <Buffer 03 04 23 42>
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的無符號16位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
例子:
var buf = new Buffer(4);
buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);
console.log(buf);
buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);
console.log(buf);
// <Buffer de ad be ef>
// <Buffer ad de ef be>
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的無符號32位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
例子:
var buf = new Buffer(4);
buf.writeUInt32BE(0xfeedface, 0);
console.log(buf);
buf.writeUInt32LE(0xfeedface, 0);
console.log(buf);
// <Buffer fe ed fa ce>
// <Buffer ce fa ed fe>
false向buffer的指定偏移位置中寫入value。
注意,value必須是一個合法的無符號32位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
運作和buffer.writeUInt8相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的有符號16位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
運作和buffer.writeUInt16相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的有符號32位整形數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
運作和buffer.writeUInt32相同,除非 buffer 內(nèi)容中有包含了作為2的補碼的有符號值。
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的32位浮點數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
例子:
var buf = new Buffer(4);
buf.writeFloatBE(0xcafebabe, 0);
console.log(buf);
buf.writeFloatLE(0xcafebabe, 0);
console.log(buf);
// <Buffer 4f 4a fe bb>
// <Buffer bb fe 4a 4f>
false向buffer的指定偏移位置根據(jù)特定的endian字節(jié)序?qū)懭?code>value。
注意,value必須是一個合法的64位雙精度數(shù)。
將noAssert設(shè)置為true將跳過value和offset的驗證。這意味著value可能會過大,或者offset超過buffer的末尾導致value被丟棄,這個參數(shù)除非你十分有把握否則你不應去使用它,默認為false。
例子:
var buf = new Buffer(8);
buf.writeDoubleBE(0xdeadbeefcafebabe, 0);
console.log(buf);
buf.writeDoubleLE(0xdeadbeefcafebabe, 0);
console.log(buf);
// <Buffer 43 eb d5 b7 dd f9 5f d7>
// <Buffer d7 5f f9 dd b7 d5 eb 43>
使用指定的value填充 buffer。如果offset(默認為0)和end(默認為buffer.length)沒有指定,將會填充整個 buffer。
var b = new Buffer(50);
b.fill("h");
創(chuàng)建一個 buffer 內(nèi)的值(bytes)的迭代器。這個函數(shù)會被自動調(diào)用當 buffer 被用于for..of語句中時。
創(chuàng)建一個 buffer 的索引的迭代器。
創(chuàng)建一個[index, byte]數(shù)組迭代器。
Number 默認值: 50
表示有多少字節(jié)會被返回當調(diào)用buffer.inspect()時。它可以被用戶的模塊所覆蓋。
注意這是一個由require('buffer')返回的buffer模塊的屬性,并不是全局Buffer對象或buffer 實例的。
Buffers可以被 ES6 的for..of語法迭代:
var buf = new Buffer([1, 2, 3]);
for (var b of buf)
console.log(b)
// 1
// 2
// 3
另外的,buffer.values(),buffer.keys()和buffer.entries()方法都可以被用來創(chuàng)建迭代器。
返回一個不被池管理的Buffer。
為了避免創(chuàng)建許多單個的被分配內(nèi)存的小 Buffer 的垃圾回收開銷。默認得,分配小于4 KB 的空間將會被從一個更大的被分配好內(nèi)存的對象(allocated object)中切片(sliced)得到。這個方法改進了性能以及內(nèi)存占用,因為 V8 的垃圾回收機制不再需要追蹤和清理許多的小對象。
當開發(fā)者需要將池中一小塊數(shù)據(jù)保留不確定的一段時間,較為妥當?shù)霓k法是用 SlowBuffer創(chuàng)建一個不被池管理的Buffer實例并將相應數(shù)據(jù)拷貝出來。
// need to keep around a few small chunks of memory
var store = [];
socket.on('readable', function() {
var data = socket.read();
// allocate for retained data
var sb = new SlowBuffer(10);
// copy the data into the new allocation
data.copy(sb, 0, 0, 10);
store.push(sb);
});
請謹慎使用,僅作為開發(fā)者察覺到在應用中有過度的內(nèi)存保留時的最后手段。