wake-up-neo.net

Konvertierung zwischen Strings und ArrayBuffers

Gibt es eine allgemein akzeptierte Technik, um JavaScript-Strings effizient in ArrayBuffers und umgekehrt zu konvertieren? Insbesondere möchte ich in der Lage sein, den Inhalt eines ArrayBuffers in localStorage zu schreiben und ihn zurückzulesen.

205
kpozin

Update 2016 - fünf Jahre später gibt es nun neue Methoden in den Spezifikationen (siehe Unterstützung unten), um zwischen Strings und typisierten Arrays mit der richtigen Kodierung zu konvertieren.

TextEncoder

Die TextEncoder steht für :

Die TextEncoder-Schnittstelle stellt einen Encoder für eine bestimmte Methode dar das ist eine bestimmte Zeichencodierung, wie utf-8iso-8859-2, koi8, cp1261, gbk, ... Ein Encoder nimmt einen Strom von Codepunkten als Eingabe und gibt einen Bytestrom aus.

Notiz ändern, da das Obige geschrieben wurde: (ibid.)

Hinweis: Firefox, Chrome und Opera haben früher die Kodierung unterstützt andere Typen als utf-8 (wie utf-16, iso-8859-2, koi8, cp1261 und gbk). Ab Firefox 48 [...], Chrome 54 [...] und Opera 41, Nr Andere Codierungstypen als utf-8 sind verfügbar, um mit .__ übereinzustimmen. die spez. *

*) Aktualisierte Spezifikationen (W3) und hier (whatwg).

Nachdem Sie eine Instanz von TextEncoder erstellt haben, wird eine Zeichenfolge verwendet und mit einem bestimmten Codierungsparameter codiert:

if (!("TextEncoder" in window)) 
  alert("Sorry, this browser does not support TextEncoder...");

var enc = new TextEncoder(); // always utf-8
console.log(enc.encode("This is a string converted to a Uint8Array"));

Sie verwenden dann natürlich den .buffer-Parameter für den resultierenden Uint8Array, um die darunterliegende ArrayBuffer bei Bedarf in eine andere Ansicht zu konvertieren.

Stellen Sie nur sicher, dass die Zeichen in der Zeichenfolge dem Kodierungsschema entsprechen. Wenn Sie beispielsweise Zeichen außerhalb des UTF-8-Bereichs verwenden, werden diese in zwei Byte statt einem Byte kodiert.

Zur allgemeinen Verwendung würden Sie die UTF-16-Codierung für Dinge wie localStorage verwenden.

TextDecoder

Der umgekehrte Prozess verwendet ebenfalls die TextDecoder :

Die TextDecoder-Schnittstelle repräsentiert einen Decoder für eine bestimmte Methode das ist eine bestimmte Zeichencodierung, wie utf-8, iso-8859-2, koi8, cp1261, gbk, ... Ein Decoder nimmt einen Stream von Bytes als Eingabe auf und gibt .__ aus. ein Strom von Codepunkten.

Alle verfügbaren Dekodierungsarten finden Sie hier .

if (!("TextDecoder" in window))
  alert("Sorry, this browser does not support TextDecoder...");

var enc = new TextDecoder("utf-8");
var arr = new Uint8Array([84,104,105,115,32,105,115,32,97,32,85,105,110,116,
                          56,65,114,114,97,121,32,99,111,110,118,101,114,116,
                          101,100,32,116,111,32,97,32,115,116,114,105,110,103]);
console.log(enc.decode(arr));

Die MDN StringView-Bibliothek

Eine Alternative dazu ist die Verwendung der StringView-Bibliothek (lizenziert als lgpl-3.0), deren Ziel:

  • erstellen einer C-ähnlichen Schnittstelle für Zeichenfolgen (d. h. ein Array von Zeichencodes - ein ArrayBufferView in JavaScript) basierend auf der JavaScript ArrayBuffer-Schnittstelle
  • eine stark erweiterbare Bibliothek erstellen, die jeder durch das Hinzufügen von Methoden zum Objekt StringView.prototype erweitern kann
  • erstellen einer Sammlung von Methoden für solche stringähnlichen Objekte (seit jetzt: stringViews), die strikt auf Zahlenarrays angewendet werden anstatt neue unveränderliche JavaScript-Zeichenfolgen zu erstellen
  • zur Verwendung mit anderen Unicode-Kodierungen als den Standard-UTF-16-DOMStrings von JavaScript

gibt viel mehr Flexibilität. Es ist jedoch erforderlich, dass wir diese Bibliothek verlinken oder einbetten, während TextEncoder/TextDecoder in moderne Browser integriert ist.

Unterstützung

Stand Juli/2018:

TextEncoder (experimentell, auf Standardspur)

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     ?     |     -     |     38

°) 18: Firefox 18 implemented an earlier and slightly different version
of the specification.

WEB WORKER SUPPORT:

Experimental, On Standard Track

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     ?     |     -     |     38

Data from MDN - `npm i -g mdncomp` by epistemex
72
user1693593

Obwohl Dennis und gengkev Lösungen zur Verwendung von Blob/FileReader funktionieren, würde ich diesen Ansatz nicht empfehlen. Es ist eine asynchrone Herangehensweise an ein einfaches Problem und viel langsamer als eine direkte Lösung. Ich habe einen Post in html5rocks mit einer einfacheren und (viel schnelleren) Lösung erstellt: http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from- String

Und die Lösung ist:

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;
}

EDIT:

Die Encoding API hilft bei der Lösung der String-Konvertierung Problem. Schauen Sie sich die Antwort von Jeff Posnik auf Html5Rocks.com auf den obigen Originalartikel an.

Auszug:

Mit der Encoding-API ist es einfach, zwischen unformatierten Bytes und systemeigenen JavaScript-Zeichenfolgen zu übersetzen, unabhängig davon, mit welcher der vielen Standardcodierungen Sie arbeiten müssen.

<pre id="results"></pre>

<script>
  if ('TextDecoder' in window) {
    // The local files to be fetched, mapped to the encoding that they're using.
    var filesToEncoding = {
      'utf8.bin': 'utf-8',
      'utf16le.bin': 'utf-16le',
      'Macintosh.bin': 'Macintosh'
    };

    Object.keys(filesToEncoding).forEach(function(file) {
      fetchAndDecode(file, filesToEncoding[file]);
    });
  } else {
    document.querySelector('#results').textContent = 'Your browser does not support the Encoding API.'
  }

  // Use XHR to fetch `file` and interpret its contents as being encoded with `encoding`.
  function fetchAndDecode(file, encoding) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', file);
    // Using 'arraybuffer' as the responseType ensures that the raw data is returned,
    // rather than letting XMLHttpRequest decode the data first.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
      if (this.status == 200) {
        // The decode() method takes a DataView as a parameter, which is a wrapper on top of the ArrayBuffer.
        var dataView = new DataView(this.response);
        // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder
        var decoder = new TextDecoder(encoding);
        var decodedString = decoder.decode(dataView);
        // Add the decoded file's text to the <pre> element on the page.
        document.querySelector('#results').textContent += decodedString + '\n';
      } else {
        console.error('Error while requesting', file, this);
      }
    };
    xhr.send();
  }
</script>
170
mangini

Sie können TextEncoder und TextDecoder aus dem Encoding-Standard verwenden, der durch die stringencoding-Bibliothek polyfill wird, um String in und aus ArrayBuffers zu konvertieren:

var uint8array = new TextEncoder().encode(string);
var string = new TextDecoder(encoding).decode(uint8array);
66

Blob ist viel langsamer als String.fromCharCode(null,array);

das schlägt jedoch fehl, wenn der Array-Puffer zu groß wird. Die beste Lösung, die ich gefunden habe, ist, String.fromCharCode(null,array); zu verwenden und sie in Vorgänge aufzuteilen, die den Stack nicht sprengen, aber schneller sind als ein einzelnes Zeichen.

Die beste Lösung für große Arraypuffer ist:

function arrayBufferToString(buffer){

    var bufView = new Uint16Array(buffer);
    var length = bufView.length;
    var result = '';
    var addition = Math.pow(2,16)-1;

    for(var i = 0;i<length;i+=addition){

        if(i + addition > length){
            addition = length - i;
        }
        result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition));
    }

    return result;

}

Ich fand das etwa 20 mal schneller als mit Blob. Es funktioniert auch für große Saiten mit mehr als 100 MB.

33
Ryan Weinstein

Basierend auf der Antwort von gengkev habe ich Funktionen für beide Arten erstellt, weil BlobBuilder String und ArrayBuffer verarbeiten kann:

function string2ArrayBuffer(string, callback) {
    var bb = new BlobBuilder();
    bb.append(string);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result);
    }
    f.readAsArrayBuffer(bb.getBlob());
}

und

function arrayBuffer2String(buf, callback) {
    var bb = new BlobBuilder();
    bb.append(buf);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result)
    }
    f.readAsText(bb.getBlob());
}

Ein einfacher Test:

string2ArrayBuffer("abc",
    function (buf) {
        var uInt8 = new Uint8Array(buf);
        console.log(uInt8); // Returns `Uint8Array { 0=97, 1=98, 2=99}`

        arrayBuffer2String(buf, 
            function (string) {
                console.log(string); // returns "abc"
            }
        )
    }
)
20
Dennis

Im Folgenden werden binäre Zeichenfolgen aus Array-Puffern abgerufen

Ich würde empfehlen, nicht zu verwenden

var binaryString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));

weil es

  1. crashes bei großen Puffern (jemand schrieb über die "magische" Größe von 246300, aber ich bekam Maximum call stack size exceeded Fehler bei 120000 Byte-Puffer (Chrome 29))
  2. es hat wirklich schlechte Leistung (siehe unten)

Wenn Sie gerade eine synchrone Lösung benötigen, verwenden Sie so etwas

var
  binaryString = '',
  bytes = new Uint8Array(arrayBuffer),
  length = bytes.length;
for (var i = 0; i < length; i++) {
  binaryString += String.fromCharCode(bytes[i]);
}

es ist so langsam wie das vorherige, funktioniert aber korrekt. Es scheint, dass es zum Zeitpunkt des Schreibens keine recht schnelle, synchrone Lösung für dieses Problem gibt (alle in diesem Thema genannten Bibliotheken verwenden für ihre synchronen Funktionen den gleichen Ansatz).

Was ich wirklich empfehle, ist die Verwendung von Blob + FileReader

function readBinaryStringFromArrayBuffer (arrayBuffer, onSuccess, onFail) {
  var reader = new FileReader();
  reader.onload = function (event) {
    onSuccess(event.target.result);
  };
  reader.onerror = function (event) {
    onFail(event.target.error);
  };
  reader.readAsBinaryString(new Blob([ arrayBuffer ],
    { type: 'application/octet-stream' }));
}

der einzige Nachteil (nicht für alle) ist, dass es asynchronous ist. Und es ist etwa 8-10 mal schneller als die bisherigen Lösungen! (Einige Details: Eine synchrone Lösung in meiner Umgebung benötigte 950 bis 1050 ms für 2,4 MB Puffer, aber die Lösung mit FileReader hatte etwa 100 bis 120 ms für dieselbe Datenmenge. Und ich habe beide synchronen Lösungen auf 100 Kb Puffer getestet und sie haben fast die gleiche Zeit in Anspruch genommen, so dass die Schleife nicht viel langsamer ist.

BTW hier: Wie konvertiert man ArrayBuffer von und nach String author vergleicht zwei Ansätze wie ich und erhält völlig entgegengesetzte Ergebnisse ( sein Testcode ist hier ) Warum so unterschiedliche Ergebnisse? Wahrscheinlich wegen seiner Test-Saite, die 1 Kb lang ist (er nannte sie "veryLongStr"). Mein Puffer war ein wirklich großes JPEG-Bild mit einer Größe von 2,4 MB.

14

Im Gegensatz zu den Lösungen hier musste ich UTF-8-Daten konvertieren. Zu diesem Zweck habe ich die folgenden beiden Funktionen mit dem (un) escape/(en) decodeURIComponent-Trick codiert. Der Speicherplatz ist ziemlich verschwenderisch, da die 9-fache Länge der codierten utf8-Zeichenfolge zugewiesen wird. Diese sollten jedoch von gc wiederhergestellt werden. Verwenden Sie sie einfach nicht für 100 MB Text.

function utf8AbFromStr(str) {
    var strUtf8 = unescape(encodeURIComponent(str));
    var ab = new Uint8Array(strUtf8.length);
    for (var i = 0; i < strUtf8.length; i++) {
        ab[i] = strUtf8.charCodeAt(i);
    }
    return ab;
}

function strFromUtf8Ab(ab) {
    return decodeURIComponent(escape(String.fromCharCode.apply(null, ab)));
}

Überprüfen, dass es funktioniert:

strFromUtf8Ab(utf8AbFromStr('latinкирилицаαβγδεζηあいうえお'))
-> "latinкирилицаαβγδεζηあいうえお"
12
Moshev

(Update Siehe bitte die zweite Hälfte dieser Antwort, wo ich (hoffentlich) eine vollständigere Lösung bereitgestellt habe.)

Ich bin auch auf diese Ausgabe gestoßen, die folgende Arbeit für mich in FF 6 (für eine Richtung):

var buf = new ArrayBuffer( 10 );
var view = new Uint8Array( buf );
view[ 3 ] = 4;
alert(Array.prototype.slice.call(view).join(""));

Leider erhalten Sie natürlich ASCII - Textdarstellungen der Werte im Array und nicht Zeichen. Es sollte (sollte) jedoch noch viel effizienter sein als eine Schleife. Für das obige Beispiel lautet das Ergebnis 0004000000 und nicht mehrere Nullzeichen und ein Chr (4).

Bearbeiten:

Nach einem Blick auf MDChier können Sie eine ArrayBuffer aus einer Array wie folgt erstellen:

var arr = new Array(23);
// New Uint8Array() converts the Array elements
//  to Uint8s & creates a new ArrayBuffer
//  to store them in & a corresponding view.
//  To get at the generated ArrayBuffer,
//  you can then access it as below, with the .buffer property
var buf = new Uint8Array( arr ).buffer;

Um Ihre ursprüngliche Frage zu beantworten, können Sie ArrayBuffer <-> String folgendermaßen konvertieren:

var buf, view, str;
buf = new ArrayBuffer( 256 );
view = new Uint8Array( buf );

view[ 0 ] = 7; // Some dummy values
view[ 2 ] = 4;

// ...

// 1. Buffer -> String (as byte array "list")
str = bufferToString(buf);
alert(str); // Alerts "7,0,4,..."

// 1. String (as byte array) -> Buffer    
buf = stringToBuffer(str);
alert(new Uint8Array( buf )[ 2 ]); // Alerts "4"

// Converts any ArrayBuffer to a string
//  (a comma-separated list of ASCII ordinals,
//  NOT a string of characters from the ordinals
//  in the buffer elements)
function bufferToString( buf ) {
    var view = new Uint8Array( buf );
    return Array.prototype.join.call(view, ",");
}
// Converts a comma-separated ASCII ordinal string list
//  back to an ArrayBuffer (see note for bufferToString())
function stringToBuffer( str ) {
    var arr = str.split(",")
      , view = new Uint8Array( arr );
    return view.buffer;
}

Der Einfachheit halber ist hier eine function zum Konvertieren eines unformatierten Unicode String in eine ArrayBuffer (funktioniert nur mit ASCII-/1-Byte-Zeichen)

function rawStringToBuffer( str ) {
    var idx, len = str.length, arr = new Array( len );
    for ( idx = 0 ; idx < len ; ++idx ) {
        arr[ idx ] = str.charCodeAt(idx) & 0xFF;
    }
    // You may create an ArrayBuffer from a standard array (of values) as follows:
    return new Uint8Array( arr ).buffer;
}

// Alerts "97"
alert(new Uint8Array( rawStringToBuffer("abc") )[ 0 ]);

Das obige erlaubt es Ihnen, wieder von ArrayBuffer -> String & zurück zu ArrayBuffer zu gelangen, wo der String zB gespeichert werden kann. .localStorage :)

Hoffe das hilft,

Dan

12
Dan Phillimore

Ich habe festgestellt, dass ich Probleme mit diesem Ansatz hatte, im Wesentlichen, weil ich versuchte, die Ausgabe in eine Datei zu schreiben, und diese nicht ordnungsgemäß codiert war. Da JS anscheinend die UCS-2-Codierung ( source , source ) zu verwenden scheint, müssen wir diese Lösung noch einen Schritt weiter ausdehnen. Hier ist meine erweiterte Lösung, die für mich funktioniert.

Ich hatte keine Schwierigkeiten mit generischem Text, aber wenn es sich um Arabisch oder Koreanisch handelte, hatte die Ausgabedatei nicht alle Zeichen, sondern zeigte stattdessen Fehlerzeichen 

Dateiausgabe: ","10k unit":"",Follow:"Õ©íüY‹","Follow %{screen_name}":"%{screen_name}U“’Õ©íü",Tweet:"ĤüÈ","Tweet %{hashtag}":"%{hashtag} ’ĤüÈY‹","Tweet to %{name}":"%{name}U“xĤüÈY‹"},ko:{"%{followers_count} followers":"%{followers_count}…X \Ì","100K+":"100Ì tÁ","10k unit":"Ì è",Follow:"\°","Follow %{screen_name}":"%{screen_name} Ø \°X0",K:"œ",M:"1Ì",Tweet:"¸","Tweet %{hashtag}":"%{hashtag}

Original: ","10k unit":"万",Follow:"フォローする","Follow %{screen_name}":"%{screen_name}さんをフォロー",Tweet:"ツイート","Tweet %{hashtag}":"%{hashtag} をツイートする","Tweet to %{name}":"%{name}さんへツイートする"},ko:{"%{followers_count} followers":"%{followers_count}명의 팔로워","100K+":"100만 이상","10k unit":"만 단위",Follow:"팔로우","Follow %{screen_name}":"%{screen_name} 님 팔로우하기",K:"천",M:"백만",Tweet:"트윗","Tweet %{hashtag}":"%{hashtag}

Ich habe die Informationen aus dennis 'Lösung genommen und diesem Beitrag fand ich.

Hier ist mein Code:

function encode_utf8(s) {
  return unescape(encodeURIComponent(s));
}

function decode_utf8(s) {
  return decodeURIComponent(escape(s));
}

 function ab2str(buf) {
   var s = String.fromCharCode.apply(null, new Uint8Array(buf));
   return decode_utf8(decode_utf8(s))
 }

function str2ab(str) {
   var s = encode_utf8(str)
   var buf = new ArrayBuffer(s.length); 
   var bufView = new Uint8Array(buf);
   for (var i=0, strLen=s.length; i<strLen; i++) {
     bufView[i] = s.charCodeAt(i);
   }
   return bufView;
 }

Dadurch kann ich den Inhalt ohne Codierungsprobleme in einer Datei speichern.

Wie es funktioniert: Es benötigt im Wesentlichen die einzelnen 8-Byte-Chunks, aus denen ein UTF-8-Zeichen besteht, und speichert sie als Einzelzeichen (daher kann ein auf diese Weise erstelltes UTF-8-Zeichen aus 1-4 dieser Zeichen bestehen ) . UTF-8 codiert Zeichen in einem Format, das zwischen 1 und 4 Byte lang ist. Was wir hier tun, kodiert den Sting in einer URI-Komponente und nimmt diese Komponente und übersetzt sie in das entsprechende 8-Byte-Zeichen. Auf diese Weise verlieren wir die Informationen nicht, die von UTF8-Zeichen mit einer Länge von mehr als 1 Byte angegeben werden.

6
Dieghito

Nun, hier ist ein etwas komplizierter Weg, das Gleiche zu tun:

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());

Edit: BlobBuilder wurde lange Zeit zugunsten des Blob-Konstruktors abgelehnt, der bei meinem ersten Beitrag nicht existierte. Hier ist eine aktualisierte Version. (Und ja, das war schon immer ein dummer Weg, die Konvertierung durchzuführen, aber es war nur zum Spaß!)

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]));
4
gengkev

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õÎW0 Náò8ìÉÉPPv\0"

4
user3832931

wenn Sie ein großes Array-Beispiel arr.length=1000000 verwendet haben, können Sie diesen Code verwenden, um Stapelrückrufprobleme zu vermeiden 

function ab2str(buf) {
var bufView = new Uint16Array(buf);
var unis =""
for (var i = 0; i < bufView.length; i++) {
    unis=unis+String.fromCharCode(bufView[i]);
}
return unis
}

umkehrfunktion Mangini Antwort von oben

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;
}
4
Elbaz

Nachdem ich mit Manginis Lösung für die Konvertierung von ArrayBuffer in String - ab2str (die die eleganteste und nützlichste ist, die ich gefunden habe - danke!) Gespielt habe, hatte ich einige Probleme beim Umgang mit großen Arrays. Noch spezifischer bewirkt der Aufruf von String.fromCharCode.apply(null, new Uint16Array(buf)); einen Fehler: 

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

Um es zu lösen (Bypass), habe ich mich entschieden, die Eingabe ArrayBuffer in Chunks zu behandeln. Die modifizierte Lösung lautet also:

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;
}

Die Blockgröße ist auf 2^16 eingestellt, da dies die Größe ist, die ich in meiner Entwicklungslandschaft gefunden habe. Wenn Sie einen höheren Wert festlegen, wird derselbe Fehler erneut angezeigt. Sie kann geändert werden, indem Sie die Variable CHUNK_SIZE auf einen anderen Wert setzen. Es ist wichtig, eine gerade Zahl zu haben.

Hinweis zur Leistung - Ich habe für diese Lösung keine Leistungstests durchgeführt. Da es jedoch auf der vorherigen Lösung basiert und große Arrays verarbeiten kann, sehe ich keinen Grund, warum ich es nicht verwenden sollte.

Alle Kommentare sind willkommen (-:

3
yinon

Siehe hier: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView (Eine C-ähnliche Schnittstelle für Zeichenfolgen, die auf der JavaScript-ArrayBuffer-Schnittstelle basieren)

2
pascov

Der "native" Binärstring, den atob () zurückgibt, ist ein 1 Byte langes Array.

Wir sollten also nicht 2 Byte in einem Charakter speichern.

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;
}
1
wdhwg001

Ich habe das benutzt und arbeitet für mich.

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;
}
0
Elias Vargas

Ja:

const encstr = (`TextEncoder` in window) ? new TextEncoder().encode(str) : Uint8Array.from(str, c => c.codePointAt(0));
0
Denis Giffeler

Ich würde empfehlen, keine veralteten APIs wie BlobBuilder zu verwenden

BlobBuilder wurde vom Blob-Objekt seit langem verworfen. Vergleichen Sie den Code in Dennis 'Antwort - wo BlobBuilder verwendet wird - mit dem folgenden Code:

function arrayBufferGen(str, cb) {

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

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

  f.readAsArrayBuffer(b);

}

Beachten Sie, wie viel sauberer und weniger aufgebläht dies im Vergleich zu der veralteten Methode ist ... Ja, das ist definitiv etwas zu bedenken.

0
realkstrawn93
  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;
  }
0
Admir
var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);

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

0
Ganesh S