Преобразование между строками и ArrayBuffers - PullRequest
222 голосов
/ 06 августа 2011

Существует ли общепринятый метод эффективного преобразования строк JavaScript в ArrayBuffers и наоборот? В частности, я хотел бы иметь возможность записать содержимое ArrayBuffer в localStorage и прочитать его обратно.

Ответы [ 20 ]

4 голосов
/ 16 августа 2017

ES2015:

a=Uint8Array.from(s,(x)=>x.charCodeAt(0))

Uint8Array (33) [2, 134, 140, 186, 82, 70, 108, 182, 233, 40, 143, 247, 29, 76, 245, 206, 29, 87, 48, 160, 78, 225, 242, 56, 236, 201, 80, 80, 152, 118, 92, 144, 48

s=String.fromCharCode.apply(null,a)

"ºRFl¶é (÷ LõÎW0Náò8ìÉPPv \ 0"

4 голосов
/ 29 января 2012

Хорошо, вот несколько запутанный способ сделать то же самое:

var string = "Blah blah blah", output;
var bb = new (window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder)();
bb.append(string);
var f = new FileReader();
f.onload = function(e) {
  // do whatever
  output = e.target.result;
}
f.readAsArrayBuffer(bb.getBlob());

Редактировать: BlobBuilder уже давно устарел в пользу конструктора Blob, которого не было, когдаЯ впервые написал этот пост.Вот обновленная версия.(И да, это всегда был очень глупый способ сделать преобразование, но это было просто для удовольствия!)

var string = "Blah blah blah", output;
var f = new FileReader();
f.onload = function(e) {
  // do whatever
  output = e.target.result;
};
f.readAsArrayBuffer(new Blob([string]));
3 голосов
/ 19 января 2014

После игры с решением Манджини для преобразования из ArrayBuffer в String - ab2str (которое является самым элегантным и полезным из всех, что я нашел - спасибо!) У меня возникли некоторые проблемы при работе с большими массивами. Более конкретно, вызов String.fromCharCode.apply(null, new Uint16Array(buf)); выдает ошибку:

arguments array passed to Function.prototype.apply is too large.

Чтобы решить эту проблему (обойти), я решил обработать ввод ArrayBuffer кусками. Таким образом, модифицированное решение:

function ab2str(buf) {
   var str = "";
   var ab = new Uint16Array(buf);
   var abLen = ab.length;
   var CHUNK_SIZE = Math.pow(2, 16);
   var offset, len, subab;
   for (offset = 0; offset < abLen; offset += CHUNK_SIZE) {
      len = Math.min(CHUNK_SIZE, abLen-offset);
      subab = ab.subarray(offset, offset+len);
      str += String.fromCharCode.apply(null, subab);
   }
   return str;
}

Размер порции установлен на 2^16, потому что это был размер, который я нашел для работы в моей среде разработки. Установка более высокого значения привела к повторению этой же ошибки. Его можно изменить, установив для переменной CHUNK_SIZE другое значение. Важно иметь четное число.

Примечание по производительности - я не проводил никаких тестов производительности для этого решения. Однако, поскольку он основан на предыдущем решении и может обрабатывать большие массивы, я не вижу причин, почему бы его не использовать.

Любые комментарии приветствуются (-:

2 голосов
/ 12 июня 2013

Смотрите здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView (C-подобный интерфейс для строк, основанный на интерфейсе JavaScript ArrayBuffer)

2 голосов
/ 21 июля 2018
  stringToArrayBuffer(byteString) {
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
      byteArray[i] = byteString.codePointAt(i);
    }
    return byteArray;
  }
  arrayBufferToString(buffer) {
    var byteArray = new Uint8Array(buffer);
    var byteString = '';
    for (var i = 0; i < byteArray.byteLength; i++) {
      byteString += String.fromCodePoint(byteArray[i]);
    }
    return byteString;
  }
1 голос
/ 10 января 2017

«Собственная» двоичная строка, которую возвращает atob (), представляет собой массив из 1 байта на символ.

Так что мы не должны хранить 2 байта в символе.

var arrayBufferToString = function(buffer) {
  return String.fromCharCode.apply(null, new Uint8Array(buffer));
}

var stringToArrayBuffer = function(str) {
  return (new Uint8Array([].map.call(str,function(x){return x.charCodeAt(0)}))).buffer;
}
0 голосов
/ 22 мая 2014

Я бы рекомендовал НЕ использовать устаревшие API, такие как BlobBuilder

BlobBuilder уже давно устарел в объекте Blob.Сравните код в ответе Дениса - где используется BlobBuilder - с кодом ниже:

function arrayBufferGen(str, cb) {

  var b = new Blob([str]);
  var f = new FileReader();

  f.onload = function(e) {
    cb(e.target.result);
  }

  f.readAsArrayBuffer(b);

}

Обратите внимание, насколько он чище и менее раздутый по сравнению с устаревшим методом ... Да, это определенно что-торассмотреть здесь.

0 голосов
/ 23 января 2018

Да

const encstr = (`TextEncoder` in window) ? new TextEncoder().encode(str) : Uint8Array.from(str, c => c.codePointAt(0));
0 голосов
/ 31 марта 2015
var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);

См. https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode

0 голосов
/ 09 августа 2016

Я использовал это и работает для меня.

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}



function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}
...