Uint8Array per stringere in Javascript

Ho alcuni dati codificati UTF-8 che vivono in un intervallo di elementi Uint8Array in Javascript. C’è un modo efficace per decodificarli con una stringa javascript normale (credo che Javascript usi Unicode a 16 bit)? Non desidero aggiungere un carattere alla volta poiché la concatenazione di stringhe diventerebbe troppo intensa per la CPU.

TextEncoder e TextDecoder dallo standard di codifica , che è TextEncoder TextDecoder dalla libreria stringencoding , converte tra stringhe e ArrayBuffers:

 var uint8array = new TextEncoder("utf-8").encode("¢"); var string = new TextDecoder("utf-8").decode(uint8array); 

Questo dovrebbe funzionare:

 // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt /* utf.js - UTF-8 <=> UTF-16 convertion * * Copyright (C) 1999 Masanao Izumo  * Version: 1.0 * LastModified: Dec 25 1999 * This library is free. You can redistribute it and/or modify it. */ function Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; while(i < len) { c = array[i++]; switch(c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } 

È un po 'più pulito come le altre soluzioni perché non utilizza alcun hack né dipende dalle funzioni di Browser JS, ad esempio funziona anche in altri ambienti JS.

Guarda la demo di JSFiddle .

Vedi anche le domande correlate: qui e qui

Ecco cosa uso:

 var str = String.fromCharCode.apply(null, uint8Arr); 

Trovato in una delle applicazioni di esempio di Chrome, anche se questo è pensato per blocchi di dati più grandi in cui stai bene con una conversione asincrona.

 /** * Converts an array buffer to a string * * @private * @param {ArrayBuffer} buf The buffer to convert * @param {Function} callback The function to call when conversion is complete */ function _arrayBufferToString(buf, callback) { var bb = new Blob([new Uint8Array(buf)]); var f = new FileReader(); f.onload = function(e) { callback(e.target.result); }; f.readAsText(bb); } 

Fai quello che dice @Sudhir, e poi per ottenere una stringa dall’elenco di numeri separati da virgola:

 for (var i=0; i 

Questo ti darà la stringa che vuoi, se è ancora rilevante

Nel nodo ” Buffer istanze del Buffer sono anche istanze di Uint8Array “, quindi in questo caso buf.toString() funziona.

La soluzione fornita da Albert funziona bene fino a quando la funzione fornita viene invocata raramente e viene utilizzata solo per gli array di dimensioni modeste, altrimenti è egregiamente inefficiente. Ecco una soluzione JavaScript vanilla avanzata che funziona sia per Node che per browser e presenta i seguenti vantaggi:

• Funziona in modo efficiente per tutte le dimensioni degli array di ottetti

• Non genera stringhe intermedie da buttare via

• Supporta caratteri a 4 byte sui moderni motori JS (altrimenti “?” È sostituito)

 var utf8ArrayToStr = (function () { var charCache = new Array(128); // Preallocate the cache for the common single byte chars var charFromCodePt = String.fromCodePoint || String.fromCharCode; var result = []; return function (array) { var codePt, byte1; var buffLen = array.length; result.length = 0; for (var i = 0; i < buffLen;) { byte1 = array[i++]; if (byte1 <= 0x7F) { codePt = byte1; } else if (byte1 <= 0xDF) { codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F); } else if (byte1 <= 0xEF) { codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F); } else if (String.fromCodePoint) { codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F); } else { codePt = 63; // Cannot convert four byte code points, so use "?" instead i += 3; } result.push(charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt))); } return result.join(''); }; })(); 
 class UTF8{ static encode(str:string){return new UTF8().encode(str)} static decode(data:Uint8Array){return new UTF8().decode(data)} private EOF_byte:number = -1; private EOF_code_point:number = -1; private encoderError(code_point) { console.error("UTF8 encoderError",code_point) } private decoderError(fatal, opt_code_point?):number { if (fatal) console.error("UTF8 decoderError",opt_code_point) return opt_code_point || 0xFFFD; } private inRange(a:number, min:number, max:number) { return min <= a && a <= max; } private div(n:number, d:number) { return Math.floor(n / d); } private stringToCodePoints(string:string) { /** @type {Array.} */ let cps = []; // Based on http://www.w3.org/TR/WebIDL/#idl-DOMString let i = 0, n = string.length; while (i < string.length) { let c = string.charCodeAt(i); if (!this.inRange(c, 0xD800, 0xDFFF)) { cps.push(c); } else if (this.inRange(c, 0xDC00, 0xDFFF)) { cps.push(0xFFFD); } else { // (inRange(c, 0xD800, 0xDBFF)) if (i == n - 1) { cps.push(0xFFFD); } else { let d = string.charCodeAt(i + 1); if (this.inRange(d, 0xDC00, 0xDFFF)) { let a = c & 0x3FF; let b = d & 0x3FF; i += 1; cps.push(0x10000 + (a << 10) + b); } else { cps.push(0xFFFD); } } } i += 1; } return cps; } private encode(str:string):Uint8Array { let pos:number = 0; let codePoints = this.stringToCodePoints(str); let outputBytes = []; while (codePoints.length > pos) { let code_point:number = codePoints[pos++]; if (this.inRange(code_point, 0xD800, 0xDFFF)) { this.encoderError(code_point); } else if (this.inRange(code_point, 0x0000, 0x007f)) { outputBytes.push(code_point); } else { let count = 0, offset = 0; if (this.inRange(code_point, 0x0080, 0x07FF)) { count = 1; offset = 0xC0; } else if (this.inRange(code_point, 0x0800, 0xFFFF)) { count = 2; offset = 0xE0; } else if (this.inRange(code_point, 0x10000, 0x10FFFF)) { count = 3; offset = 0xF0; } outputBytes.push(this.div(code_point, Math.pow(64, count)) + offset); while (count > 0) { let temp = this.div(code_point, Math.pow(64, count - 1)); outputBytes.push(0x80 + (temp % 64)); count -= 1; } } } return new Uint8Array(outputBytes); } private decode(data:Uint8Array):string { let fatal:boolean = false; let pos:number = 0; let result:string = ""; let code_point:number; let utf8_code_point = 0; let utf8_bytes_needed = 0; let utf8_bytes_seen = 0; let utf8_lower_boundary = 0; while (data.length > pos) { let _byte = data[pos++]; if (_byte == this.EOF_byte) { if (utf8_bytes_needed != 0) { code_point = this.decoderError(fatal); } else { code_point = this.EOF_code_point; } } else { if (utf8_bytes_needed == 0) { if (this.inRange(_byte, 0x00, 0x7F)) { code_point = _byte; } else { if (this.inRange(_byte, 0xC2, 0xDF)) { utf8_bytes_needed = 1; utf8_lower_boundary = 0x80; utf8_code_point = _byte - 0xC0; } else if (this.inRange(_byte, 0xE0, 0xEF)) { utf8_bytes_needed = 2; utf8_lower_boundary = 0x800; utf8_code_point = _byte - 0xE0; } else if (this.inRange(_byte, 0xF0, 0xF4)) { utf8_bytes_needed = 3; utf8_lower_boundary = 0x10000; utf8_code_point = _byte - 0xF0; } else { this.decoderError(fatal); } utf8_code_point = utf8_code_point * Math.pow(64, utf8_bytes_needed); code_point = null; } } else if (!this.inRange(_byte, 0x80, 0xBF)) { utf8_code_point = 0; utf8_bytes_needed = 0; utf8_bytes_seen = 0; utf8_lower_boundary = 0; pos--; code_point = this.decoderError(fatal, _byte); } else { utf8_bytes_seen += 1; utf8_code_point = utf8_code_point + (_byte - 0x80) * Math.pow(64, utf8_bytes_needed - utf8_bytes_seen); if (utf8_bytes_seen !== utf8_bytes_needed) { code_point = null; } else { let cp = utf8_code_point; let lower_boundary = utf8_lower_boundary; utf8_code_point = 0; utf8_bytes_needed = 0; utf8_bytes_seen = 0; utf8_lower_boundary = 0; if (this.inRange(cp, lower_boundary, 0x10FFFF) && !this.inRange(cp, 0xD800, 0xDFFF)) { code_point = cp; } else { code_point = this.decoderError(fatal, _byte); } } } } //Decode string if (code_point !== null && code_point !== this.EOF_code_point) { if (code_point <= 0xFFFF) { if (code_point > 0)result += String.fromCharCode(code_point); } else { code_point -= 0x10000; result += String.fromCharCode(0xD800 + ((code_point >> 10) & 0x3ff)); result += String.fromCharCode(0xDC00 + (code_point & 0x3ff)); } } } return result; } 

`

Prova queste funzioni,

 var JsonToArray = function(json) { var str = JSON.stringify(json, null, 0); var ret = new Uint8Array(str.length); for (var i = 0; i < str.length; i++) { ret[i] = str.charCodeAt(i); } return ret }; var binArrayToJson = function(binArray) { var str = ""; for (var i = 0; i < binArray.length; i++) { str += String.fromCharCode(parseInt(binArray[i])); } return JSON.parse(str) } 

fonte: https://gist.github.com/tomfa/706d10fed78c497731ac , complimenti a Tomfa

Sto usando questo frammento di typescript:

 function UInt8ArrayToString(uInt8Array: Uint8Array): string { var s: string = "["; for(var i: number = 0; i < uInt8Array.byteLength; i++) { if( i > 0 ) s += ", "; s += uInt8Array[i]; } s += "]"; return s; } 

Rimuovi le annotazioni sul tipo se hai bisogno della versione JavaScript. Spero che questo ti aiuti!