Ich habe eine ArrayBuffer
, die eine mit UTF-8 codierte Zeichenfolge enthält, und ich kann keine Standardmethode zum Konvertieren einer solchen ArrayBuffer
in eine JS String
finden (die ich verstehe, wird mit UTF-16 codiert).
Ich habe diesen Code an zahlreichen Stellen gesehen, aber ich kann nicht erkennen, wie er mit UTF-8-Codepunkten funktioniert, die länger als 1 Byte sind.
return String.fromCharCode.apply(null, new Uint8Array(data));
Ebenso kann ich keine Standardmethode zum Konvertieren von einer String
in eine UTF-8-codierte ArrayBuffer
finden.
function stringToUint(string) {
var string = btoa(unescape(encodeURIComponent(string))),
charList = string.split(''),
uintArray = [];
for (var i = 0; i < charList.length; i++) {
uintArray.Push(charList[i].charCodeAt(0));
}
return new Uint8Array(uintArray);
}
function uintToString(uintArray) {
var encodedString = String.fromCharCode.apply(null, uintArray),
decodedString = decodeURIComponent(escape(atob(encodedString)));
return decodedString;
}
Ich habe mit etwas Hilfe aus dem Internet diese kleinen Funktionen gemacht, sie sollten Ihre Probleme lösen! Hier ist das arbeitende JSFiddle .
EDIT:
Da die Quelle des Uint8Array extern ist und Sie atob
nicht verwenden können, müssen Sie sie nur entfernen ( working Geige ):
function uintToString(uintArray) {
var encodedString = String.fromCharCode.apply(null, uintArray),
decodedString = decodeURIComponent(escape(encodedString));
return decodedString;
}
TextEncoder und TextDecoder verwenden
var uint8array = new TextEncoder("utf-8").encode("Plain Text");
var string = new TextDecoder().decode(uint8array);
console.log(uint8array ,string )
Das sollte funktionieren:
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/* utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo <[email protected]>
* 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;
}
Es ist etwas sauberer als die anderen Lösungen, da es keine Hacks verwendet oder von Browser JS-Funktionen abhängt, z. funktioniert auch in anderen JS-Umgebungen.
Schauen Sie sich die JSFiddle Demo an.
Für Encoding over auf Github gibt es einen Polyfill: Text-Encoding . Es ist für Node oder den Browser einfach, und die Readme-Datei empfiehlt Folgendes:
var uint8array = TextEncoder(encoding).encode(string);
var string = TextDecoder(encoding).decode(uint8array);
Wenn ich mich erinnere, ist 'utf-8'
die encoding
, die Sie benötigen, und natürlich müssen Sie Ihren Puffer umschließen:
var uint8array = new Uint8Array(utf8buffer);
Ich hoffe es funktioniert für dich genauso gut wie für mich.
Wenn Sie dies im Browser tun, sind keine Zeichenkodierungsbibliotheken integriert. Sie können jedoch mit ___.by:
function pad(n) {
return n.length < 2 ? "0" + n : n;
}
var array = new Uint8Array(data);
var str = "";
for( var i = 0, len = array.length; i < len; ++i ) {
str += ( "%" + pad(array[i].toString(16)))
}
str = decodeURIComponent(str);
Hier ist eine Demo, die eine 3-Byte-UTF-8-Einheit decodiert: http://jsfiddle.net/Z9pQE/
Die Methoden readAsArrayBuffer und readAsText eines FileReader - Objekts konvertieren ein Blob-Objekt in einen ArrayBuffer oder einen asynchronen DOMString.
Ein Blob-Objekttyp kann beispielsweise aus einem Rohtext- oder Byte-Array erstellt werden.
let blob = new Blob([text], { type: "text/plain" });
let reader = new FileReader();
reader.onload = event =>
{
let buffer = event.target.result;
};
reader.readAsArrayBuffer(blob);
Ich denke, es ist besser, dies in ein Versprechen zu packen:
function textToByteArray(text)
{
let blob = new Blob([text], { type: "text/plain" });
let reader = new FileReader();
let done = function() { };
reader.onload = event =>
{
done(new Uint8Array(event.target.result));
};
reader.readAsArrayBuffer(blob);
return { done: function(callback) { done = callback; } }
}
function byteArrayToText(bytes, encoding)
{
let blob = new Blob([bytes], { type: "application/octet-stream" });
let reader = new FileReader();
let done = function() { };
reader.onload = event =>
{
done(event.target.result);
};
if(encoding) { reader.readAsText(blob, encoding); } else { reader.readAsText(blob); }
return { done: function(callback) { done = callback; } }
}
let text = "\uD83D\uDCA9 = \u2661";
textToByteArray(text).done(bytes =>
{
console.log(bytes);
byteArrayToText(bytes, 'UTF-8').done(text =>
{
console.log(text); // ???? = ♡
});
});
Das Hauptproblem von Programmierern, die nach einer Konvertierung von einem Byte-Array in einen String suchen, ist die UTF-8-Codierung (Komprimierung) von Unicode-Zeichen. Dieser Code wird Ihnen helfen:
var getString = function (strBytes) {
var MAX_SIZE = 0x4000;
var codeUnits = [];
var highSurrogate;
var lowSurrogate;
var index = -1;
var result = '';
while (++index < strBytes.length) {
var codePoint = Number(strBytes[index]);
if (codePoint === (codePoint & 0x7F)) {
} else if (0xF0 === (codePoint & 0xF0)) {
codePoint ^= 0xF0;
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
} else if (0xE0 === (codePoint & 0xE0)) {
codePoint ^= 0xE0;
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
} else if (0xC0 === (codePoint & 0xC0)) {
codePoint ^= 0xC0;
codePoint = (codePoint << 6) | (strBytes[++index] ^ 0x80);
}
if (!isFinite(codePoint) || codePoint < 0 || codePoint > 0x10FFFF || Math.floor(codePoint) != codePoint)
throw RangeError('Invalid code point: ' + codePoint);
if (codePoint <= 0xFFFF)
codeUnits.Push(codePoint);
else {
codePoint -= 0x10000;
highSurrogate = (codePoint >> 10) | 0xD800;
lowSurrogate = (codePoint % 0x400) | 0xDC00;
codeUnits.Push(highSurrogate, lowSurrogate);
}
if (index + 1 == strBytes.length || codeUnits.length > MAX_SIZE) {
result += String.fromCharCode.apply(null, codeUnits);
codeUnits.length = 0;
}
}
return result;
}
Alles Gute !
Für diejenigen, die in Node.js> = 0.1.99 arbeiten
Node.js bietet ein eingebautes Modul mit dem Namen StringDecoder
, das ausdrücklich zum Dekodieren von Multibyte-Puffern in Strings ausgelegt ist.
https://nodejs.org/api/string_decoder.html
Über den Link oben:
Das Modul string_decoder bietet eine API zum Dekodieren von Pufferobjekten in Strings auf eine Weise, bei der kodierte UTF-8- und UTF-16-Zeichen mit mehreren Bytes erhalten bleiben
Beispiel (aus den oben genannten Dokumenten entlehnt):
const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');
const cent = Buffer.from([0xC2, 0xA2]);
console.log(decoder.write(cent)); // ¢
const euro = Buffer.from([0xE2, 0x82, 0xAC]);
console.log(decoder.write(euro)); // €