ArrayBuffers используются для транспортировки необработанных данных, и на них полагаются несколько новых API, включая WebSockets , Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) и WebWorkers . Однако, поскольку они недавно появились в мире JavaScript, иногда их неправильно интерпретируют или используют.
Семантически ArrayBuffer — это просто массив байтов, просматриваемый через определенную маску. Эта маска, экземпляр ArrayBufferView , определяет, как байты выравниваются, чтобы соответствовать ожидаемой структуре содержимого. Например, если вы знаете, что байты в ArrayBuffer представляют собой массив 16-битных целых чисел без знака, вы просто обертываете ArrayBuffer в представление Uint16Array
и можете манипулировать его элементами, используя синтаксис скобок, как если бы Uint16Array
был целочисленным массивом:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
Один из распространенных практических вопросов, касающихся ArrayBuffer, — как преобразовать String
в ArrayBuffer
и наоборот. Поскольку ArrayBuffer фактически представляет собой массив байтов, это преобразование требует, чтобы оба конца договорились о том, как представлять символы в строке в виде байтов. Вы, вероятно, уже видели это «соглашение» раньше: это кодировка символов String (а обычными «условиями соглашения» являются, например, Unicode UTF-16 и iso8859-1). Таким образом, предположим, что вы и другая сторона договорились о кодировке UTF-16, код преобразования может быть примерно таким:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Обратите внимание на использование Uint16Array
. Это представление ArrayBuffer, которое выравнивает байты ArrayBuffers как 16-битные элементы. Он не обрабатывает саму кодировку символов, которая обрабатывается как Unicode с помощью String.fromCharCode
и str.charCodeAt
.
На популярный вопрос StackOverflow по этому поводу есть ответ, получивший большое количество голосов, с несколько запутанным решением преобразования: создать FileReader
, который будет действовать как преобразователь, и передать в него Blob
, содержащий строку. Хотя этот метод работает, он плохо читаем и, подозреваю, медленный. Поскольку необоснованные подозрения привели к множеству ошибок в истории человечества, давайте применим здесь более научный подход. Я выполнил оба метода с помощью jsperf , и результат подтверждает мои подозрения, и вы можете посмотреть демо-версию здесь .
В Chrome 20 использование прямого кода манипуляции ArrayBuffer
в этой статье почти в 27 раз быстрее, чем использование метода FileReader
/ Blob
.
ArrayBuffers используются для транспортировки необработанных данных, и на них полагаются несколько новых API, включая WebSockets , Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) и WebWorkers . Однако, поскольку они недавно появились в мире JavaScript, иногда их неправильно интерпретируют или используют.
Семантически ArrayBuffer — это просто массив байтов, просматриваемый через определенную маску. Эта маска, экземпляр ArrayBufferView , определяет, как байты выравниваются, чтобы соответствовать ожидаемой структуре содержимого. Например, если вы знаете, что байты в ArrayBuffer представляют собой массив 16-битных целых чисел без знака, вы просто обертываете ArrayBuffer в представление Uint16Array
и можете манипулировать его элементами, используя синтаксис скобок, как если бы Uint16Array
был целочисленным массивом:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
Один из распространенных практических вопросов, касающихся ArrayBuffer, — как преобразовать String
в ArrayBuffer
и наоборот. Поскольку ArrayBuffer фактически представляет собой массив байтов, это преобразование требует, чтобы оба конца договорились о том, как представлять символы в строке в виде байтов. Вы, вероятно, видели это «соглашение» раньше: это кодировка символов String (а обычными «условиями соглашения» являются, например, Unicode UTF-16 и iso8859-1). Таким образом, предположим, что вы и другая сторона договорились о кодировке UTF-16, код преобразования может быть примерно таким:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Обратите внимание на использование Uint16Array
. Это представление ArrayBuffer, которое выравнивает байты ArrayBuffers как 16-битные элементы. Он не обрабатывает саму кодировку символов, которая обрабатывается как Unicode с помощью String.fromCharCode
и str.charCodeAt
.
На популярный вопрос StackOverflow по этому поводу есть ответ, получивший большое количество голосов, с несколько запутанным решением преобразования: создать FileReader
, который будет действовать как преобразователь, и передать в него Blob
, содержащий строку. Хотя этот метод работает, он плохо читаем и, подозреваю, медленный. Поскольку необоснованные подозрения привели к множеству ошибок в истории человечества, давайте применим здесь более научный подход. Я выполнил оба метода с помощью jsperf , и результат подтверждает мои подозрения, и вы можете посмотреть демо-версию здесь .
В Chrome 20 использовать код прямой манипуляции ArrayBuffer
в этой статье почти в 27 раз быстрее, чем использовать метод FileReader
/ Blob
.
ArrayBuffers используются для транспортировки необработанных данных, и на них полагаются несколько новых API, включая WebSockets , Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) и WebWorkers . Однако, поскольку они недавно появились в мире JavaScript, иногда их неправильно интерпретируют или используют.
Семантически ArrayBuffer — это просто массив байтов, просматриваемый через определенную маску. Эта маска, экземпляр ArrayBufferView , определяет, как байты выравниваются, чтобы соответствовать ожидаемой структуре содержимого. Например, если вы знаете, что байты в ArrayBuffer представляют собой массив 16-битных целых чисел без знака, вы просто обертываете ArrayBuffer в представление Uint16Array
и можете манипулировать его элементами, используя синтаксис скобок, как если бы Uint16Array
был целочисленным массивом:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
Один из распространенных практических вопросов, касающихся ArrayBuffer, — как преобразовать String
в ArrayBuffer
и наоборот. Поскольку ArrayBuffer фактически представляет собой массив байтов, это преобразование требует, чтобы оба конца договорились о том, как представлять символы в строке в виде байтов. Вы, вероятно, уже видели это «соглашение» раньше: это кодировка символов String (а обычными «условиями соглашения» являются, например, Unicode UTF-16 и iso8859-1). Таким образом, предположим, что вы и другая сторона договорились о кодировке UTF-16, код преобразования может быть примерно таким:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Обратите внимание на использование Uint16Array
. Это представление ArrayBuffer, которое выравнивает байты ArrayBuffer как 16-битные элементы. Он не обрабатывает саму кодировку символов, которая обрабатывается как Unicode с помощью String.fromCharCode
и str.charCodeAt
.
На популярный вопрос StackOverflow по этому поводу есть ответ, получивший большое количество голосов, с несколько запутанным решением преобразования: создать FileReader
, который будет действовать как преобразователь, и передать в него Blob
, содержащий строку. Хотя этот метод работает, он плохо читаем и, подозреваю, медленный. Поскольку необоснованные подозрения привели к множеству ошибок в истории человечества, давайте применим здесь более научный подход. Я выполнил оба метода с помощью jsperf , и результат подтверждает мои подозрения, и вы можете посмотреть демо-версию здесь .
В Chrome 20 использовать код прямой манипуляции ArrayBuffer
в этой статье почти в 27 раз быстрее, чем использовать метод FileReader
/ Blob
.