简体   繁体   English

如何从 ArrayBuffer 中获取二进制字符串?

[英]How to get binary string from ArrayBuffer?

What is the way to obtain binary string from ArrayBuffer in JavaScript?从JavaScript中的ArrayBuffer获取二进制字符串的方法是什么?

I don't want to encode the bytes, just get the binary representation as String.我不想对字节进行编码,只是将二进制表示形式作为字符串。

Thanks in advance!提前致谢!

The following code will consistently convert an ArrayBuffer to a String and back again without losing or adding any additional bytes.以下代码将始终将ArrayBuffer转换为String并再次返回,而不会丢失或添加任何额外字节。

function ArrayBufferToString(buffer) {
    return BinaryToString(String.fromCharCode.apply(null, Array.prototype.slice.apply(new Uint8Array(buffer))));
}

function StringToArrayBuffer(string) {
    return StringToUint8Array(string).buffer;
}

function BinaryToString(binary) {
    var error;

    try {
        return decodeURIComponent(escape(binary));
    } catch (_error) {
        error = _error;
        if (error instanceof URIError) {
            return binary;
        } else {
            throw error;
        }
    }
}

function StringToBinary(string) {
    var chars, code, i, isUCS2, len, _i;

    len = string.length;
    chars = [];
    isUCS2 = false;
    for (i = _i = 0; 0 <= len ? _i < len : _i > len; i = 0 <= len ? ++_i : --_i) {
        code = String.prototype.charCodeAt.call(string, i);
        if (code > 255) {
            isUCS2 = true;
            chars = null;
            break;
        } else {
            chars.push(code);
        }
    }
    if (isUCS2 === true) {
        return unescape(encodeURIComponent(string));
    } else {
        return String.fromCharCode.apply(null, Array.prototype.slice.apply(chars));
    }
}

function StringToUint8Array(string) {
    var binary, binLen, buffer, chars, i, _i;
    binary = StringToBinary(string);
    binLen = binary.length;
    buffer = new ArrayBuffer(binLen);
    chars  = new Uint8Array(buffer);
    for (i = _i = 0; 0 <= binLen ? _i < binLen : _i > binLen; i = 0 <= binLen ? ++_i : --_i) {
        chars[i] = String.prototype.charCodeAt.call(binary, i);
    }
    return chars;
}

I tested it by round-tripping the following values in this jsfiddle: http://jsfiddle.net/potatosalad/jrdLV/我通过在这个 jsfiddle 中来回传递以下值来测试它: http : //jsfiddle.net/potatosalad/jrdLV/

(String) "abc" -> (ArrayBuffer) -> (String) "abc"
(String) "aΩc" -> (ArrayBuffer) -> (String) "aΩc"
(Uint8Array) [0,1,255] -> (ArrayBuffer) -> (String) -> (Uint8Array) [0,1,255]
(Uint16Array) [0,1,256,65535] -> (ArrayBuffer) -> (String) -> (Uint16Array) [0,1,256,65535]
(Uint32Array) [0,1,256,65536,4294967295] -> (ArrayBuffer) -> (String) -> (Uint32Array) [0,1,256,65536,4294967295]

This has been made much simpler by additions to JavaScript in recent years – here's a one-line method to convert a Uint8Array into a binary-encoded string:近年来,通过对 JavaScript 的添加,这变得更加简单——这是将 Uint8Array 转换为二进制编码字符串的单行方法:

const toBinString = (bytes) =>
  bytes.reduce((str, byte) => str + byte.toString(2).padStart(8, '0'), '');

Example:例子:

console.log(toBinString(Uint8Array.from([42, 100, 255, 0])))
// => '00101010011001001111111100000000'

If you're starting with an ArrayBuffer, create a Uint8Array "view" of the buffer to pass into this method:如果您从 ArrayBuffer 开始,请创建缓冲区的 Uint8Array“视图”以传递给此方法:

const view = new Uint8Array(myArrayBuffer);
console.log(toBinString(view));

Source: the Libauth library ( binToBinString method )来源: Libauth库( binToBinString 方法

This will give you a binary string from a typed array这将为您提供来自类型化数组的二进制字符串

var bitsPerByte = 8;
var array = new Uint8Array([0, 50, 100, 170, 200, 255]);
var string = "";

function repeat(str, num) {
    if (str.length === 0 || num <= 1) {
        if (num === 1) {
            return str;
        }

        return '';
    }

    var result = '',
        pattern = str;

    while (num > 0) {
        if (num & 1) {
            result += pattern;
        }

        num >>= 1;
        pattern += pattern;
    }

    return result;
}

function lpad(obj, str, num) {
    return repeat(str, num - obj.length) + obj;
}

Array.prototype.forEach.call(array, function (element) {
    string += lpad(element.toString(2), "0", bitsPerByte);
});

console.log(string);

Output is输出是

000000000011001001100100101010101100100011111111

On jsfiddlejsfiddle 上

Or perhaps you are asking about this?或者也许你在问这个?

function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
}

Note: that using apply in this manner means that you can hit the argument limitation (some 16000 elements or so), and then you will have to loop through the array elements instead.注意:以这种方式使用apply意味着您可以达到参数限制(大约 16000 个元素左右),然后您将不得不循环遍历数组元素。

On html5rockshtml5rocks 上

I realize this is a very old question, but I wanted to add one more possible case/solution since I landed on this from a search:我意识到这是一个非常古老的问题,但我想添加一个更多可能的案例/解决方案,因为我是通过搜索找到这个问题的:

I wanted an async/await version of FileReader.readAsBinaryString() because I am a capricious person and the callback interface annoyed me:我想要一个FileReader.readAsBinaryString()的异步/等待版本,因为我是一个反复无常的人,回调接口让我很烦:

// Suppose `file` exists

let fr = new FileReader()
let string1

fr.onload = ({ target: { result }}) => string1 = result
fr.readAsBinaryString(file)

console.log(string1)

Additionally, MDN says that FileReader.readAsBinaryString() only exists for backward compatibility, and FileReader.readAsArrayBuffer() is recommended instead .此外,MDN 表示FileReader.readAsBinaryString()的存在只是为了向后兼容,建议使用FileReader.readAsArrayBuffer()

There are new methods available on Blob / File that give you text , ArrayBuffer s, and stream s, but no binary strings. Blob / File上有一些新方法可以为您提供textArrayBufferstream s,但没有二进制字符串。 Heeding MDN's advice, I figured we could go from ArrayBuffer to binary string using the new methods, and indeed we can:听从 MDN 的建议,我认为我们可以使用新方法将 go 从ArrayBuffer转换为二进制字符串,而且我们确实可以:

// Again, suppose `file` exists

let ab, bufferToString, string2

bufferToString = (buffer) => {
    const bytes = new Uint8Array(buffer)
    return bytes.reduce((string, byte) => (string + String.fromCharCode(byte)), "")
}

ab = await file.arrayBuffer()
string2 = bufferToString(ab)

console.log(string2)

Assuming this is done in the same browser console:假设这是在同一个浏览器控制台中完成的:

string1 === string2 // true

Whether this is intelligence or stupidity is left to the reader.这是聪明还是愚蠢留给读者。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM