Rolf B: Binary String verarbeiten

Beitrag lesen

problematische Seite

Hallo pl,

ja, muss er. Und? Wir sprachen von JavaScript.

BTW:

Natürlich gibt es in JS keinen Datentyp byte, genausowenig gibt es einen Solchen in anderen PLs.

Das ist falsch. C, C++, C# und Java kennen einen byte-Datentyp (in C/C++ als char oder unsigned char, in C# als byte oder signed byte, in Java als byte), der als 8-bit Wert definiert ist. D.h. ein char[] in C oder ein byte[] in C#/Java belegt ein Byte pro Element.

Bei einem Uint8Array in JavaScript ist das - soweit ich das bei Tante Google erfahren konnte - genauso.

Was ich aber auch gefunden habe, ist, dass die V8 Engine in Chrome 1-byte und 2-byte Strings kennt. D.h. es ist möglich, dass dein "readAsBinaryString" tatsächlich einen String mit einem Byte pro Zeichen liefert. Das sollte Dir als JS Programmierer aber egal sein, du kannst erwarten dass die JS Engine das vor Dir versteckt.

Damit nochmal zu deiner Ausgangsfrage:

[escape() ist deprecated] Welche andere Möglichkeiten gibt es zum Verarbeiten eines BinaryString in JS?

charCodeAt hast Du ja mittlerweile gefunden. Aber das, was Du in deinem Artikel beschreibst, ist nach wie vor irreführend. charCodeAt liefert den Code eines ZEICHENS in einem String. Ein String in JavaScript ist LAUT SPEC als UTF-16 codiert, nicht UTF-8. Diese Umcodierung passiert nur dann, wenn Du ihn in einen Blob steckst, weil UTF-8 im Web die Standardcodierung für Unicode-Strings ist. Und readAsBinaryString erzeugt aus dem Blob dann einen String, der aus jedem Byte genau ein Zeichen macht, ohne Rücksicht darauf, ob die Bytesequenz im Blob einen String in einem bestimmten Encoding darstellt oder nicht. DIESER String ist wiederum in der JavaScript-Darstellung für Strings gespeichert, laut Spec also mit 2 Bytes pro Zeichen, laut Aussage aus der Quelle oben ggf. auch technisch optimiert auf 1 Byte pro Zeichen. Das ist aber rein intern. Ich habe folgendes gemacht:

b = new Blob(["äöü"]);   // -> Blob(6) { size: 6, type: "" }
fr = new FileReader();
fr.readAsBinaryString(b);
bs = fr.result;          // -> "äöü"
b2 = new Blob([bs]);     // -> Blob(12) { size: 12, type: "" }

Das war im Chrome-Debugger, also mit V8. D.h. der Binary String wird bei erneuter Blobifizierung erneut UTF-8 codiert und verdoppelt seine Länge (weil alle Bytewerte jenseits der 127 liegen). Selbst WENN Chrome fr.result intern als einbytigen String gespeichert hätte, er fasst die Bytewerte immer noch als Unicode-Codepoints im Intervall [0..255] auf.

Du kannst den von readAsBinaryString gelieferten String also durchaus benutzen, um die Wertigkeiten der Bytes im Blob zu ermitteln. Auf der Abstraktionsebene von JavaScript enthält dieser String aber keine Bytes. Sondern Zeichen.

Vermeiden kannst Du dieses Verwirrspiel nur, wenn Du readAsArrayBuffer verwendest, einen DataView darauflegst und die get/set Methoden für Uint8 verwendest.

Rolf

--
sumpsi - posui - clusi