2015-11-13 12 views
7

Javascript ArrayBuffer hoặc TypedArrays không có bất kỳ loại phương thức appendByte(), appendBytes() hoặc appendBuffer() nào. Vì vậy, nếu tôi muốn điền vào một ArrayBuffer một giá trị tại một thời điểm, làm thế nào để làm điều đó?Làm cách nào để chắp thêm byte, nhiều byte và bộ đệm vào ArrayBuffer trong javascript?

var firstVal = 0xAB;    // 1 byte 
var secondVal = 0x3D7F   // 2 bytes 
var anotherUint8Array = someArr; 

var buffer = new ArrayBuffer(); // I don't know the length yet 
var bufferArr = new UInt8Array(buffer); 

// following methods do not exist. What are the alternatives for each?? 
bufferArr.appendByte(firstVal); 
bufferArr.appendBytes(secondVal); 
bufferArr.appendBuffer(anotherUint8Array); 
+0

là một mảng, sử dụng cú pháp mảng 'r [i] = x' ví dụ: https://github.com/rndme/download/blob/master/download.js#L69 cũng xem lại cú pháp cho hàm tạo Uint8Array: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array#Syntax - bạn cần kích thước trên bộ đệm mảng đó để có thể sử dụng nó như vậy .... – dandavis

+1

Bạn không thể sửa đổi kích thước bộ đệm sau khi nó được tạo ra –

Trả lời

8

Bạn có thể tạo mới TypedArray với một mới ArrayBuffer, nhưng bạn không thể thay đổi kích thước của một bộ đệm hiện

function concatTypedArrays(a, b) { // a, b TypedArray of same type 
    var c = new (a.constructor)(a.length + b.length); 
    c.set(a, 0); 
    c.set(b, a.length); 
    return c; 
} 

Bây giờ có thể làm

var a = new Uint8Array(2), 
    b = new Uint8Array(3); 
a[0] = 1; a[1] = 2; 
b[0] = 3; b[1] = 4; 
concatTypedArrays(a, b); // [1, 2, 3, 4, 0] Uint8Array length 5 

Nếu bạn muốn sử dụng các loại khác nhau, hãy đi qua Uint8Array làm đơn vị nhỏ nhất là byte, tức là

function concatBuffers(a, b) { 
    return concatTypedArrays(
     new Uint8Array(a.buffer || a), 
     new Uint8Array(b.buffer || b) 
    ).buffer; 
} 

Điều này có nghĩa .length sẽ làm việc như mong đợi, bây giờ bạn có thể chuyển đổi này vào mảng gõ của bạn lựa chọn (chắc chắn rằng nó là một loại mà sẽ chấp nhận .byteLength của bộ đệm mặc dù)


Từ đây, bạn có thể triển khai bất kỳ phương pháp nào bạn thích để ghép nối dữ liệu của bạn, ví dụ:

function concatBytes(ui8a, byte) { 
    var b = new Uint8Array(1); 
    b[0] = byte; 
    return concatTypedArrays(ui8a, b); 
} 

var u8 = new Uint8Array(0); 
u8 = concatBytes(u8, 0x80); // [128] 
+0

Cảm ơn @Paul S. Nó sẽ có được tốt đẹp cho các chức năng cơ bản như là một phần của spec và thực hiện nguyên bản, nhưng giải pháp của bạn là khá tốt. Một câu hỏi tôi vẫn có làm thế nào bạn sẽ nối thêm một byte, cho phép nói một giá trị 4 byte duy nhất cho một typedarray. Chúng ta có thể lặp và gọi hàm 'concatBytes' được đề xuất của bạn nhiều lần cho mỗi byte đơn, nhưng nó có thể được thực hiện theo cách tốt hơn không? – codneto

+0

@codneto lưu trữ nhiều byte của bạn như thế nào? ví dụ. nếu bạn đang sử dụng ints, làm thế nào để bạn biết sự khác biệt giữa '0x3D7F' và' 0x00003D7F'? Và có, tôi đồng ý nên có một số 'concat' bản địa, nhưng tôi không nghĩ rằng nên có một bản địa' push' hoặc _length_ thay đổi - đó không phải là cách đánh mảng làm việc –

+0

S, tôi có một số chức năng mà trả lại 4 byte giá trị mà tôi cần phải thêm vào bộ đệm. Tôi cũng đang đọc một số byte từ một dòng và thêm vào bộ đệm, và đôi khi dựa trên một số cờ tôi phải đọc 1, 2 hoặc 4 giá trị byte, tất cả đều cần phải được nối thêm vào bộ đệm. Làm thế nào tôi nên thực hiện thêm các giá trị đa byte này vào bộ đệm? – codneto

1

Câu trả lời của Paul cho phép bạn nối một TypedArray với TypedArray hiện có. Trong ES6, bạn có thể sử dụng chức năng sau đây để nối nhiều TypedArrays:

function concatenate(resultConstructor, ...arrays) { 
    let totalLength = 0; 
    for (const arr of arrays) { 
     totalLength += arr.length; 
    } 
    const result = new resultConstructor(totalLength); 
    let offset = 0; 
    for (const arr of arrays) { 
     result.set(arr, offset); 
     offset += arr.length; 
    } 
    return result; 
} 

const ta = concatenate(Uint8Array, 
    Uint8Array.of(1, 2), Uint8Array.of(3, 4)); 
console.log(ta); // Uint8Array [1, 2, 3, 4] 
console.log(ta.buffer.byteLength); // 4 

Để thêm một byte mới là:

const byte = 3; 
concatenate(Uint8Array, Uint8Array.of(1, 2), Uint8Array.of(byte)); 

Phương pháp này được tìm thấy trong ExploringJS.

Các vấn đề liên quan