Konvertieren eines Byte-Arrays in einen String in Javascript

79

Wie konvertiere ich ein Byte-Array in einen String?

Ich habe diese Funktionen gefunden, die das Gegenteil bewirken:

function string2Bin(s) {
    var b = new Array();
    var last = s.length;

    for (var i = 0; i < last; i++) {
        var d = s.charCodeAt(i);
        if (d < 128)
            b[i] = dec2Bin(d);
        else {
            var c = s.charAt(i);
            alert(c + ' is NOT an ASCII character');
            b[i] = -1;
        }
    }
    return b;
}

function dec2Bin(d) {
    var b = '';

    for (var i = 0; i < 8; i++) {
        b = (d%2) + b;
        d = Math.floor(d/2);
    }

    return b;
}

Aber wie bringe ich die Funktionen dazu, anders herum zu arbeiten?

Vielen Dank.

Shao

user385579
quelle
Möchten Sie ein Byte-Array in eine Zeichenfolge oder ein Bit-Array in eine Zeichenfolge konvertieren?
Mcandre
Siehe auch die richtige Lösung für das utf8-Array: Uint8Array zum String in Javascript
Vadzim

Antworten:

82

Sie müssen jedes Oktett zurück auf die Zahl analysieren und diesen Wert verwenden, um ein Zeichen zu erhalten, etwa so:

function bin2String(array) {
  var result = "";
  for (var i = 0; i < array.length; i++) {
    result += String.fromCharCode(parseInt(array[i], 2));
  }
  return result;
}

bin2String(["01100110", "01101111", "01101111"]); // "foo"

// Using your string2Bin function to test:
bin2String(string2Bin("hello world")) === "hello world";

Bearbeiten: Ja, Ihre aktuelle string2Binkann in Kürze geschrieben werden:

function string2Bin(str) {
  var result = [];
  for (var i = 0; i < str.length; i++) {
    result.push(str.charCodeAt(i).toString(2));
  }
  return result;
}

Wenn Sie sich jedoch die von Ihnen verlinkte Dokumentation ansehen, geht die setBytesParameterMethode davon aus, dass das Blob-Array die Dezimalzahlen und keine Bitfolge enthält. Sie könnten also Folgendes schreiben:

function string2Bin(str) {
  var result = [];
  for (var i = 0; i < str.length; i++) {
    result.push(str.charCodeAt(i));
  }
  return result;
}

function bin2String(array) {
  return String.fromCharCode.apply(String, array);
}

string2Bin('foo'); // [102, 111, 111]
bin2String(string2Bin('foo')) === 'foo'; // true
Christian C. Salvadó
quelle
Danke für die superschnelle Antwort. Ein paar Fragen ... 1) Ihre bin2String-Funktion ist beeindruckend - nur 5 Codezeilen. Kann die Funktion string2bin geändert werden, um mehr Javascript-Funktionen zu verwenden, um die Funktion und die Unterfunktion zu verkürzen? .....
user385579
1
2) Der Grund, warum ich diese Konvertierungen benötige, ist, dass ich eine Signatur erfasse und sie konvertieren muss, um ein BLOB-Feld in der Datenbank zu füllen. Das Problem ist, dass während diese beiden Funktionen funktionieren, etwas anderes schief geht. Die Hauptsache ist, dass wenn ich ein BLOB aus der Datenbank abrufe, es in ein Byte-Array-Objekt geht. Wenn ich jedoch das BLOB in die Datenbank schreibe, nachdem ich es über die ursprüngliche Funktion ausgeführt habe, handelt es sich nicht um ein Byte-Array-Objekt. Dies könnte das Problem verursachen. Irgendwelche Ideen?
user385579
dcx.sybase.com/index.html#1101de/ulmbus_en11/… Dies ist die Syntax, mit der ich die Daten einstelle.
user385579
4
String.fromCharCode.apply(String, array)ist für sehr lange Saiten in Safari unsicher. Es gibt ein Problem in JavaScriptCore, das bedeutet, dass Funktionen nicht mehr als 65536 Argumente annehmen können, oder ein RangeError wird ausgelöst. Außerdem wird der Browser auf Arrays gesperrt, die etwas kleiner sind. Siehe bugs.webkit.org/show_bug.cgi?id=80797
Matthew
3
Fehlgeschlagen für Multi-Byte-Utf-8-Zeichen, dh: bin2String([0xE2, 0x98, 0xB9])
Brad Kent
48

Einfach applydein Byte-Array an String.fromCharCode. Zum Beispiel

String.fromCharCode.apply(null, [102, 111, 111]) gleich 'foo'.

Vorsichtsmaßnahme: Funktioniert für Arrays, die kürzer als 65535 sind. MDN-Dokumente hier .

Bogdan D.
quelle
Dies wurde bereits vor 6 Jahren durch die akzeptierte Antwort gezeigt.
Balthazar
2
aah, tatsächlich habe ich diese Zeile verpasst. Grundsätzlich suchte ich nach einem kurzen Einzeiler und lehnte diese lange und bearbeitete Antwort ab (vielleicht zu voreilig).
Bogdan D
Oh okay, das macht Sinn :)
Balthazar
11
Obwohl es sich um eine Wiederholung handelt, ist sie aufgrund ihrer Kürze besser als die akzeptierte Antwort.
Rich Apodaca
22

Probieren Sie die neue Text Encoding API aus:

// create an array view of some valid bytes
let bytesView = new Uint8Array([104, 101, 108, 108, 111]);

console.log(bytesView);

// convert bytes to string
// encoding can be specfied, defaults to utf-8 which is ascii.
let str = new TextDecoder().decode(bytesView); 

console.log(str);

// convert string to bytes
// encoding can be specfied, defaults to utf-8 which is ascii.
let bytes2 = new TextEncoder().encode(str);

// look, they're the same!
console.log(bytes2);
console.log(bytesView);

James
quelle
1
IE unterstützt es leider nicht.
Soul_man
Wenn Sie UTF-8- und IE-Unterstützung benötigen, können Sie die von der MDN-Website empfohlene Polyfill FastestSmallestTextEncoderDecoder verwenden .
Rosberg Linhares
10

Das sollte funktionieren:

String.fromCharCode(...array);

Oder

String.fromCodePoint(...array)
Rouli Freman
quelle
kurz und süß;)
abhisekp
8

Das string2Bin kann auch geschrieben werden mehr kurz und bündig, und ohne Schleifen, zu booten!

function string2Bin ( str ) {
    return str.split("").map( function( val ) { 
        return val.charCodeAt( 0 ); 
    } );
}
cmcnulty
quelle
1
Wäre gespannt, ob hinzugefügte Funktionsaufrufe dies verlangsamen.
Jocull
36
Es hat immer noch eine Schleife, es ist nur in map () versteckt.
Johannes Lumpe
4

Ich denke, das wäre effizienter:

function toBinString (arr) {
    var uarr = new Uint8Array(arr.map(function(x){return parseInt(x,2)}));
    var strings = [], chunksize = 0xffff;
    // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
    for (var i=0; i*chunksize < uarr.length; i++){
        strings.push(String.fromCharCode.apply(null, uarr.subarray(i*chunksize, (i+1)*chunksize)));
    }
    return strings.join('');
}
Lovasoa
quelle
4

Selbst wenn ich etwas spät dran bin, dachte ich, dass es für zukünftige Benutzer interessant wäre, einige Einzeiler-Implementierungen zu teilen, die ich mit ES6 durchgeführt habe.

Eine Sache, die ich abhängig von Ihrer Umgebung oder / und dem, was Sie mit den Daten tun werden, für wichtig halte, ist die Beibehaltung des vollständigen Bytewerts. Zum Beispiel (5).toString(2)geben Sie 101, aber die vollständige binäre Konvertierung ist in der Realität 00000101, und deshalb müssen Sie möglicherweise eine leftPadImplementierung erstellen , um das Zeichenfolgenbyte mit führenden Nullen zu füllen. Aber Sie brauchen es möglicherweise überhaupt nicht, wie andere Antworten gezeigt haben.

Wenn Sie das folgende Code-Snippet ausführen, wird die erste Ausgabe die Konvertierung der abcZeichenfolge in ein Byte-Array und unmittelbar danach die erneute Umwandlung des Arrays in die entsprechende Zeichenfolge sein.

// For each byte in our array, retrieve the char code value of the binary value
const binArrayToString = array => array.map(byte => String.fromCharCode(parseInt(byte, 2))).join('')

// Basic left pad implementation to ensure string is on 8 bits
const leftPad = str => str.length < 8 ? (Array(8).join('0') + str).slice(-8) : str

// For each char of the string, get the int code and convert it to binary. Ensure 8 bits.
const stringToBinArray = str => str.split('').map(c => leftPad(c.charCodeAt().toString(2)))

const array = stringToBinArray('abc')

console.log(array)
console.log(binArrayToString(array))

Balthazar
quelle
3

String zu Byte-Array: "FooBar".split('').map(c => c.charCodeAt(0));

Byte-Array zu String: [102, 111, 111, 98, 97, 114].map(c => String.fromCharCode(c)).join('');

ZaksBack
quelle
Seien Sie vorsichtig, dies wird vom IE nicht unterstützt!
Tedebus
1

Zu spät, um zu antworten, aber wenn Ihre Eingabe in Form von ASCII-Bytes erfolgt, können Sie diese Lösung ausprobieren:

function convertArrToString(rArr){
 //Step 1: Convert each element to character
 let tmpArr = new Array();
 rArr.forEach(function(element,index){
    tmpArr.push(String.fromCharCode(element));
});
//Step 2: Return the string by joining the elements
return(tmpArr.join(""));
}

function convertArrToHexNumber(rArr){
  return(parseInt(convertArrToString(rArr),16));
}
Indienaditya
quelle
1

Wenn Sie node.js verwenden , können Sie dies tun:

yourByteArray.toString('base64');
Caner
quelle
0

Es wurde keine Lösung gefunden, die mit UTF-8-Zeichen funktioniert. String.fromCharCodeist gut, bis Sie 2-Byte-Zeichen treffen.

Zum Beispiel wird Hüser als kommen[0x44,0x61,0x6e,0x69,0x65,0x6c,0x61,0x20,0x48,0xc3,0xbc,0x73,0x65,0x72]

Aber wenn Sie es mit durchgehen, String.fromCharCodehaben Sie Hüser, da jedes Byte separat in ein Zeichen konvertiert wird.

Lösung

Derzeit verwende ich folgende Lösung:

function pad(n) { return (n.length < 2 ? '0' + n : n); }
function decodeUtf8(data) {
  return decodeURIComponent(
    data.map(byte => ('%' + pad(byte.toString(16)))).join('')
  );
}
Soul_man
quelle
0

Ich hatte einige entschlüsselte Byte-Arrays mit Füllzeichen und anderen Dingen, die ich nicht brauchte, also tat ich dies (wahrscheinlich nicht perfekt, aber es funktioniert für meine begrenzte Verwendung)

var junk = String.fromCharCode.apply(null, res).split('').map(char => char.charCodeAt(0) <= 127 && char.charCodeAt(0) >= 32 ? char : '').join('');
IgnusFast
quelle
0

Wenn Ihr Array in UTF-8 codiert ist und Sie die TextDecoder-API nicht verwenden können, da sie im IE nicht unterstützt wird :

  1. Sie können die von der Mozilla Developer Network-Website empfohlene Polyfill FastestSmallestTextEncoderDecoder verwenden .
  2. Sie können diese Funktion auch auf der MDN-Website verwenden :

function utf8ArrayToString(aBytes) {
    var sView = "";
    
    for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
        nPart = aBytes[nIdx];
        
        sView += String.fromCharCode(
            nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
                /* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
                (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
            : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
                (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
            : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
                (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
            : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
                (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
            : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
                (nPart - 192 << 6) + aBytes[++nIdx] - 128
            : /* nPart < 127 ? */ /* one byte */
                nPart
        );
    }
    
    return sView;
}

let str = utf8ArrayToString([50,72,226,130,130,32,43,32,79,226,130,130,32,226,135,140,32,50,72,226,130,130,79]);

// Must show 2H₂ + O₂ ⇌ 2H₂O
console.log(str);

Rosberg Linhares
quelle
0

Die einfachste Lösung, die ich gefunden habe, ist:

var text = atob(byteArray);
William Hampshire
quelle