ArrayBuffer转为字符串,字符串转为ArrayBuffer的方法

7

这个问题以前已经得到了回答,但我肯定会说它仍然没有得到解答。

关于ArrayBuffers的文档几乎没有,更不用说具体应用程序的文档了。我已经研究了几天,但没有任何收获。

我需要尝试将从文件读取器(在这里:https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer)获取的ArrayBuffer转换为字符串,然后将该字符串转换回相同的ArrayBuffer。

例如,我已经尝试了下面这些方法:

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

function str2ab(str) {
  var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
  var bufView = new Uint16Array(buf);
  for (var i=0, strLen=str.length; i<strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return b

我收到了以下错误信息:"Uint16Array的字节长度应该是2的倍数"。
我还尝试了以下操作。
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;
}

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

我收到了这个错误:调用堆栈大小超过最大限制

看起来以下转换没有好的方法:AB --> 字符串 || 字符串 -> AB


另外我应该注意到,我正在使用https://openpgpjs.org/上的PGP加密字符串,需要注意的一件事是,我刚刚尝试了一个较小的图像文件,方法“有效”(没有引起任何错误),但生成的图像文件仍然损坏。 - Lao Tzu
1
你确实需要 ArrayBuffer 吗?为什么不使用 base64 呢? - Qwerty
我的目标基本上是实现本地客户端文件上传,使用PGP加密,再使用PGP解密,最后下载文件内容。 - Lao Tzu
尝试搜索base64和文件输入。对于上传、绘制到<img>和下载来说,它非常简单! - Qwerty
我已经可以做到以下操作了 - 将文件读取为数组缓冲区,然后将数组缓冲区内容下载为文件。 - Lao Tzu
显示剩余9条评论
3个回答

15

现在大多数浏览器都支持TextEncoderTextDecoder,Node.js也有util.TextEncoderutil.TextDecoder。这个 WHATWG 标准提供了简单的方法来在字节数组(具有 buffer 属性)和字符串之间进行转换:

const str = new TextDecoder().decode(byteArray);
const byteArray = new TextEncoder().encode(str);
const buffer = byteArray.buffer;

1
这不会从String构建一个ArrayBuffer - bryc
对不起!我忘了展示如何访问缓冲区!感谢您指出这一点,@bryc。 - John
2
感谢您的帮助编辑,@webchitect! - John

7

可以使用Blob和FileReader来实现异步方式。

您可以指定任何有效的编码方式。

function arrayBufferToString( buffer, encoding, callback ) {
    var blob = new Blob([buffer],{type:'text/plain'});
    var reader = new FileReader();
    reader.onload = function(evt){callback(evt.target.result);};
    reader.readAsText(blob, encoding);
}

function stringToArrayBuffer( string, encoding, callback ) {
    var blob = new Blob([string],{type:'text/plain;charset='+encoding});
    var reader = new FileReader();
    reader.onload = function(evt){callback(evt.target.result);};
    reader.readAsArrayBuffer(blob);
}


//example:
var buf = new Uint8Array([65,66,67]);
arrayBufferToString(buf, 'UTF-8', console.log.bind(console)); //"ABC"

stringToArrayBuffer('ABC', 'UTF-8', console.log.bind(console)); //[65,66,67]

3

赞美 cuixping 出色的回答,以下是转换函数的 TypeScript 版本。

const arrayBufferToString = (buffer: ArrayBuffer, encoding = 'UTF-8'): Promise<string> => {
  return new Promise<string>((resolve, reject) => {
    const blob = new Blob([buffer], { type: 'text/plain' });
    const reader = new FileReader();
    reader.onload = (evt) => {
      if (evt.target) {
        resolve(evt.target.result as string);
      } else {
        reject(new Error('Could not convert array to string!'));
      }
    };
    reader.readAsText(blob, encoding);
  });
};

const stringToArrayBuffer = (text: string, encoding = 'UTF-8'): Promise<ArrayBuffer> => {
  return new Promise<ArrayBuffer>((resolve, reject) => {
    const blob = new Blob([text], { type: `text/plain;charset=${encoding}` });
    const reader = new FileReader();
    reader.onload = (evt) => {
      if (evt.target) {
        resolve(evt.target.result as ArrayBuffer);
      } else {
        reject(new Error('Could not convert string to array!'));
      }
    };
    reader.readAsArrayBuffer(blob);
  });
};

您可以使用Buffer.from("string")更简单地初始化一个缓冲区。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接