Javascript 在字符串和 ArrayBuffers 之间转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6965107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:00:25  来源:igfitidea点击:

Converting between strings and ArrayBuffers

javascriptserializationarraybuffertyped-arrays

提问by kpozin

Is there a commonly accepted technique for efficiently converting JavaScript strings to ArrayBuffersand vice-versa? Specifically, I'd like to be able to write the contents of an ArrayBuffer to localStorageand to read it back.

是否有一种普遍接受的技术可以有效地将 JavaScript 字符串转换为ArrayBuffers,反之亦然?具体来说,我希望能够将 ArrayBuffer 的内容写入localStorage并读回。

采纳答案by mangini

Update 2016- five years on there are now new methods in the specs (see support below) to convert between strings and typed arrays using proper encoding.

2016更新- 五年后,规范中出现了新方法(请参阅下面的支持),可以使用正确的编码在字符串和类型化数组之间进行转换。

TextEncoder

文本编码器

The TextEncoderrepresents:

TextEncoder代表

The TextEncoderinterface represents an encoder for a specific method, that is a specific character encoding, like utf-8, iso-8859-2, koi8, cp1261, gbk, ...An encoder takes a stream of code points as input and emits a stream of bytes.

TextEncoder接口表示为具体的方法的编码器,这是一个特定的字符编码,如utf-8iso-8859-2, koi8, cp1261, gbk, ...编码器将代码点流作为输入并发出字节流。

Change note since the above was written:(ibid.)

自上述内容以来的更改说明:(同上)

Note: Firefox, Chrome and Opera used to have support for encoding types other than utf-8 (such as utf-16, iso-8859-2, koi8, cp1261, and gbk). As of Firefox 48 [...], Chrome 54 [...] and Opera 41, no other encoding types are available other than utf-8, in order to match the spec.*

注意:Firefox、Chrome 和 Opera 曾经支持 utf-8 以外的编码类型(例如 utf-16、iso-8859-2、koi8、cp1261 和 gbk)。从 Firefox 48 [...]、Chrome 54 [...] 和 Opera 41 开始,为了符合规范,除 utf-8 之外没有其他可用的编码类型。*

*) Updated specs(W3) and here(whatwg).

*)更新了规格(W3) 和这里(whatwg)。

After creating an instance of the TextEncoderit will take a string and encode it using a given encoding parameter:

创建 的实例后,TextEncoder它将获取一个字符串并使用给定的编码参数对其进行编码:

if (!("TextEncoder" in window)) 
  alert("Sorry, this browser does not support TextEncoder...");

var enc = new TextEncoder(); // always utf-8
console.log(enc.encode("This is a string converted to a Uint8Array"));

You then of course use the .bufferparameter on the resulting Uint8Arrayto convert the underlaying ArrayBufferto a different view if needed.

如果需要,您当然可以使用.buffer结果上的参数Uint8Array将底层转换ArrayBuffer为不同的视图。

Just make sure that the characters in the string adhere to the encoding schema, for example, if you use characters outside the UTF-8 range in the example they will be encoded to two bytes instead of one.

只需确保字符串中的字符符合编码模式,例如,如果您在示例中使用 UTF-8 范围之外的字符,它们将被编码为两个字节而不是一个字节。

For general use you would use UTF-16 encoding for things like localStorage.

对于一般用途,您可以将 UTF-16 编码用于localStorage.

TextDecoder

文本解码器

Likewise, the opposite process uses the TextDecoder:

同样,相反的过程使用TextDecoder

The TextDecoderinterface represents a decoder for a specific method, that is a specific character encoding, like utf-8, iso-8859-2, koi8, cp1261, gbk, ... A decoder takes a stream of bytes as input and emits a stream of code points.

TextDecoder接口表示特定方法的解码器,即特定的字符编码,例如utf-8, iso-8859-2, koi8, cp1261, gbk, ... 解码器将字节流作为输入并发出代码点流。

All available decoding types can be found here.

所有可用的解码类型都可以在这里找到。

if (!("TextDecoder" in window))
  alert("Sorry, this browser does not support TextDecoder...");

var enc = new TextDecoder("utf-8");
var arr = new Uint8Array([84,104,105,115,32,105,115,32,97,32,85,105,110,116,
                          56,65,114,114,97,121,32,99,111,110,118,101,114,116,
                          101,100,32,116,111,32,97,32,115,116,114,105,110,103]);
console.log(enc.decode(arr));

The MDN StringView library

MDN StringView 库

An alternative to these is to use the StringViewlibrary(licensed as lgpl-3.0) which goal is:

这些的替代方法是使用StringView(许可为 lgpl-3.0),其目标是:

  • to create a C-like interface for strings (i.e., an array of character codes — an ArrayBufferView in JavaScript) based upon the JavaScript ArrayBuffer interface
  • to create a highly extensible library that anyone can extend by adding methods to the object StringView.prototype
  • to create a collection of methods for such string-like objects (since now: stringViews) which work strictly on arrays of numbers rather than on creating new immutable JavaScript strings
  • to work with Unicode encodings other than JavaScript's default UTF-16 DOMStrings
  • 基于 JavaScript ArrayBuffer 接口为字符串(即字符代码数组——JavaScript 中的 ArrayBufferView)创建一个类似 C 的接口
  • 创建一个高度可扩展的库,任何人都可以通过向对象 StringView.prototype 添加方法来扩展该库
  • 为这种类似字符串的对象创建一组方法(从现在开始:stringViews),这些对象严格适用于数字数组,而不是创建新的不可变 JavaScript 字符串
  • 使用除 JavaScript 的默认 UTF-16 DOMStrings 以外的 Unicode 编码

giving much more flexibility. However, it would require us to link to or embed this library while TextEncoder/TextDecoderis being built-in in modern browsers.

给予更多的灵活性。然而,当TextEncoder/TextDecoder被内置在现代浏览器中时,它需要我们链接或嵌入这个库。

Support

支持

As of July/2018:

截至 2018 年 7 月:

TextEncoder(Experimental, On Standard Track)

TextEncoder(实验性,在标准轨道上)

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     ?     |     -     |     38

°) 18: Firefox 18 implemented an earlier and slightly different version
of the specification.

WEB WORKER SUPPORT:

Experimental, On Standard Track

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     ?     |     -     |     38

Data from MDN - `npm i -g mdncomp` by epistemex

回答by mangini

Although Dennis and gengkev solutions of using Blob/FileReader work, I wouldn't suggest taking that approach. It is an async approach to a simple problem, and it is much slower than a direct solution. I've made a post in html5rocks with a simpler and (much faster) solution: http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String

尽管使用 Blob/FileReader 的 Dennis 和 gengkev 解决方案有效,但我不建议采用这种方法。这是解决简单问题的异步方法,比直接解决方案慢得多。我在 html5rocks 中发布了一个更简单且(更快)的解决方案:http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String

And the solution is:

解决方案是:

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


EDIT:

编辑:

The Encoding API helps solving the string conversionproblem. Check out the response from Jeff Posnikon Html5Rocks.com to the above original article.

编码API可以帮助解决这个字符串转换问题。查看Html5Rocks.comJeff Posnik对上述原始文章的回复。

Excerpt:

摘抄:

The Encoding API makes it simple to translate between raw bytes and native JavaScript strings, regardless of which of the many standard encodings you need to work with.

编码 API 使原始字节和原生 JavaScript 字符串之间的转换变得简单,无论您需要使用许多标准编码中的哪一种。

<pre id="results"></pre>

<script>
  if ('TextDecoder' in window) {
    // The local files to be fetched, mapped to the encoding that they're using.
    var filesToEncoding = {
      'utf8.bin': 'utf-8',
      'utf16le.bin': 'utf-16le',
      'macintosh.bin': 'macintosh'
    };

    Object.keys(filesToEncoding).forEach(function(file) {
      fetchAndDecode(file, filesToEncoding[file]);
    });
  } else {
    document.querySelector('#results').textContent = 'Your browser does not support the Encoding API.'
  }

  // Use XHR to fetch `file` and interpret its contents as being encoded with `encoding`.
  function fetchAndDecode(file, encoding) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', file);
    // Using 'arraybuffer' as the responseType ensures that the raw data is returned,
    // rather than letting XMLHttpRequest decode the data first.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
      if (this.status == 200) {
        // The decode() method takes a DataView as a parameter, which is a wrapper on top of the ArrayBuffer.
        var dataView = new DataView(this.response);
        // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder
        var decoder = new TextDecoder(encoding);
        var decodedString = decoder.decode(dataView);
        // Add the decoded file's text to the <pre> element on the page.
        document.querySelector('#results').textContent += decodedString + '\n';
      } else {
        console.error('Error while requesting', file, this);
      }
    };
    xhr.send();
  }
</script>

回答by Ilmari Heikkinen

You can use TextEncoderand TextDecoderfrom the Encoding standard, which is polyfilled by the stringencoding library, to convert string to and from ArrayBuffers:

您可以使用TextEncoderTextDecoder来自Encoding 标准,它由stringencoding 库填充,将字符串转换为 ArrayBuffers 或从 ArrayBuffers 转换:

var uint8array = new TextEncoder().encode(string);
var string = new TextDecoder(encoding).decode(uint8array);

回答by Ryan Weinstein

Blob is much slower than String.fromCharCode(null,array);

Blob 比 String.fromCharCode(null,array);

but that fails if the array buffer gets too big. The best solution I have found is to use String.fromCharCode(null,array);and split it up into operations that won't blow the stack, but are faster than a single char at a time.

但是如果数组缓冲区变得太大,那将失败。我发现的最佳解决方案是使用String.fromCharCode(null,array);并将其拆分为不会破坏堆栈但一次比单个字符快的操作。

The best solution for large array buffer is:

大数组缓冲区的最佳解决方案是:

function arrayBufferToString(buffer){

    var bufView = new Uint16Array(buffer);
    var length = bufView.length;
    var result = '';
    var addition = Math.pow(2,16)-1;

    for(var i = 0;i<length;i+=addition){

        if(i + addition > length){
            addition = length - i;
        }
        result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition));
    }

    return result;

}

I found this to be about 20 times faster than using blob. It also works for large strings of over 100mb.

我发现这比使用 blob 快大约 20 倍。它也适用于超过 100mb 的大字符串。

回答by Dennis

Based on the answer of gengkev, I created functions for both ways, because BlobBuildercan handle String and ArrayBuffer:

根据 gengkev 的回答,我为这两种方式创建了函数,因为BlobBuilder可以处理 String 和 ArrayBuffer:

function string2ArrayBuffer(string, callback) {
    var bb = new BlobBuilder();
    bb.append(string);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result);
    }
    f.readAsArrayBuffer(bb.getBlob());
}

and

function arrayBuffer2String(buf, callback) {
    var bb = new BlobBuilder();
    bb.append(buf);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result)
    }
    f.readAsText(bb.getBlob());
}

A simple test:

一个简单的测试:

string2ArrayBuffer("abc",
    function (buf) {
        var uInt8 = new Uint8Array(buf);
        console.log(uInt8); // Returns `Uint8Array { 0=97, 1=98, 2=99}`

        arrayBuffer2String(buf, 
            function (string) {
                console.log(string); // returns "abc"
            }
        )
    }
)

回答by Konstantin Smolyanin

All the following is about getting binary strings from array buffers

以下所有内容都是关于从数组缓冲区获取二进制字符串

I'd recommend not to use

我建议不要使用

var binaryString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));

because it

因为它

  1. crasheson big buffers (somebody wrote about "magic" size of 246300 but I got Maximum call stack size exceedederror on 120000 bytes buffer (Chrome 29))
  2. it has really poor performance(see below)
  1. 在大缓冲区上崩溃(有人写了 246300 的“魔法”大小,但我Maximum call stack size exceeded在 120000 字节缓冲区(Chrome 29)上出错)
  2. 它的性能真的很差(见下文)

If you exactly need synchronous solution use something like

如果您确实需要同步解决方案,请使用类似

var
  binaryString = '',
  bytes = new Uint8Array(arrayBuffer),
  length = bytes.length;
for (var i = 0; i < length; i++) {
  binaryString += String.fromCharCode(bytes[i]);
}

it is as slow as the previous one but works correctly. It seems that at the moment of writing this there is no quite fast synchronous solution for that problem (all libraries mentioned in this topic uses the same approach for their synchronous features).

它和前一个一样慢,但工作正常。在撰写本文时,似乎没有针对该问题的快速同步解决方案(本主题中提到的所有库都使用相同的方法来处理它们的同步功能)。

But what I really recommend is using Blob+ FileReaderapproach

但我真正推荐的是使用Blob+FileReader方法

function readBinaryStringFromArrayBuffer (arrayBuffer, onSuccess, onFail) {
  var reader = new FileReader();
  reader.onload = function (event) {
    onSuccess(event.target.result);
  };
  reader.onerror = function (event) {
    onFail(event.target.error);
  };
  reader.readAsBinaryString(new Blob([ arrayBuffer ],
    { type: 'application/octet-stream' }));
}

the only disadvantage (not for all) is that it is asynchronous. And it is about 8-10 times fasterthen previous solutions! (Some details: synchronous solution on my environment took 950-1050 ms for 2.4Mb buffer but solution with FileReader had times about 100-120 ms for the same amount of data. And I have tested bothsynchronous solutions on 100Kb buffer and they have taken almost the same time, so loop is not much slower the using 'apply'.)

唯一的缺点(不是全部)是它是异步的。它以前的解决方案快 8-10 倍!(一些细节:我的环境中的同步解决方案对于 2.4Mb 缓冲区需要 950-1050 毫秒,但是使用 FileReader 的解决方案对于相同数量的数据有大约 100-120 毫秒的时间。我已经在 100Kb 缓冲区上测试了两种同步解决方案,他们已经采取了几乎在同一时间,因此使用“apply”循环不会慢很多。)

BTW here: How to convert ArrayBuffer to and from Stringauthor compares two approaches like me and get completely opposite results (his test code is here) Why so different results? Probably because of his test string that is 1Kb long (he called it "veryLongStr"). My buffer was a really big JPEG image of size 2.4Mb.

顺便说一句:How to convert ArrayBuffer to and from String作者比较像我这样的两种方法并得到完全相反的结果(他的测试代码在这里) 为什么结果如此不同?可能是因为他的测试字符串有 1Kb 长(他称之为“veryLongStr”)。我的缓冲区是一个非常大的 JPEG 图像,大小为 2.4Mb。

回答by Moshev

Unlike the solutions here, I needed to convert to/from UTF-8 data. For this purpose, I coded the following two functions, using the (un)escape/(en)decodeURIComponent trick. They're pretty wasteful of memory, allocating 9 times the length of the encoded utf8-string, though those should be recovered by gc. Just don't use them for 100mb text.

与这里的解决方案不同,我需要在 UTF-8 数据之间进行转换。为此,我使用 (un)escape/(en)decodeURIComponent 技巧编写了以下两个函数。它们非常浪费内存,分配了编码 utf8 字符串长度的 9 倍,尽管这些应该由 gc 恢复。只是不要将它们用于 100mb 文本。

function utf8AbFromStr(str) {
    var strUtf8 = unescape(encodeURIComponent(str));
    var ab = new Uint8Array(strUtf8.length);
    for (var i = 0; i < strUtf8.length; i++) {
        ab[i] = strUtf8.charCodeAt(i);
    }
    return ab;
}

function strFromUtf8Ab(ab) {
    return decodeURIComponent(escape(String.fromCharCode.apply(null, ab)));
}

Checking that it works:

检查它是否有效:

strFromUtf8Ab(utf8AbFromStr('latinкирилицаαβγδεζηあいうえお'))
-> "latinкирилицаαβγδεζηあいうえお"

回答by Dan Phillimore

(UpdatePlease see the 2nd half of this answer, where I have (hopefully) provided a more complete solution.)

更新请参阅此答案的第二部分,我(希望)在其中提供了更完整的解决方案。)

I also ran into this issue, the following works for me in FF 6 (for one direction):

我也遇到了这个问题,以下在 FF 6 中对我有用(对于一个方向):

var buf = new ArrayBuffer( 10 );
var view = new Uint8Array( buf );
view[ 3 ] = 4;
alert(Array.prototype.slice.call(view).join(""));

Unfortunately, of course, you end up with ASCII text representations of the values in the array, rather than characters. It still (should be) much more efficient than a loop, though. eg. For the example above, the result is 0004000000, rather than several null chars & a chr(4).

不幸的是,当然,您最终会得到数组中值的 ASCII 文本表示,而不是字符。不过,它仍然(应该)比循环更有效。例如。对于上面的示例,结果是0004000000, 而不是几个空字符和一个 chr(4)。

Edit:

编辑:

After looking on MDChere, you may create an ArrayBufferfrom an Arrayas follows:

此处查看MDC后,您可以从以下创建一个:ArrayBufferArray

var arr = new Array(23);
// New Uint8Array() converts the Array elements
//  to Uint8s & creates a new ArrayBuffer
//  to store them in & a corresponding view.
//  To get at the generated ArrayBuffer,
//  you can then access it as below, with the .buffer property
var buf = new Uint8Array( arr ).buffer;

To answer your original question, this allows you to convert ArrayBuffer<-> Stringas follows:

要回答您的原始问题,这允许您按如下方式转换ArrayBuffer<-> String

var buf, view, str;
buf = new ArrayBuffer( 256 );
view = new Uint8Array( buf );

view[ 0 ] = 7; // Some dummy values
view[ 2 ] = 4;

// ...

// 1. Buffer -> String (as byte array "list")
str = bufferToString(buf);
alert(str); // Alerts "7,0,4,..."

// 1. String (as byte array) -> Buffer    
buf = stringToBuffer(str);
alert(new Uint8Array( buf )[ 2 ]); // Alerts "4"

// Converts any ArrayBuffer to a string
//  (a comma-separated list of ASCII ordinals,
//  NOT a string of characters from the ordinals
//  in the buffer elements)
function bufferToString( buf ) {
    var view = new Uint8Array( buf );
    return Array.prototype.join.call(view, ",");
}
// Converts a comma-separated ASCII ordinal string list
//  back to an ArrayBuffer (see note for bufferToString())
function stringToBuffer( str ) {
    var arr = str.split(",")
      , view = new Uint8Array( arr );
    return view.buffer;
}

For convenience, here is a functionfor converting a raw Unicode Stringto an ArrayBuffer(will only work with ASCII/one-byte characters)

为方便起见,这里有一个function用于将原始 Unicode 转换String为一个ArrayBuffer(仅适用于 ASCII/一字节字符)

function rawStringToBuffer( str ) {
    var idx, len = str.length, arr = new Array( len );
    for ( idx = 0 ; idx < len ; ++idx ) {
        arr[ idx ] = str.charCodeAt(idx) & 0xFF;
    }
    // You may create an ArrayBuffer from a standard array (of values) as follows:
    return new Uint8Array( arr ).buffer;
}

// Alerts "97"
alert(new Uint8Array( rawStringToBuffer("abc") )[ 0 ]);

The above allow you to go from ArrayBuffer-> String& back to ArrayBufferagain, where the string may be stored in eg. .localStorage:)

上面允许您从ArrayBuffer-> String& 返回到ArrayBuffer再次,字符串可能存储在例如。.localStorage:)

Hope this helps,

希望这可以帮助,

Dan

回答by user3832931

In case you have binary data in a string (obtained from nodejs+ readFile(..., 'binary'), or cypress+ cy.fixture(..., 'binary'), etc), you can't use TextEncoder. It supports only utf8. Bytes with values >= 128are each turned into 2 bytes.

如果字符串中有二进制数据(从nodejs+readFile(..., 'binary')cypress+cy.fixture(..., 'binary')等获取),则不能使用TextEncoder. 它只支持utf8. 带有值的字节>= 128每个都变成 2 个字节。

ES2015:

ES2015:

a = Uint8Array.from(s, x => x.charCodeAt(0))

Uint8Array(33) [2, 134, 140, 186, 82, 70, 108, 182, 233, 40, 143, 247, 29, 76, 245, 206, 29, 87, 48, 160, 78, 225, 242, 56, 236, 201, 80, 80, 152, 118, 92, 144, 48

Uint8Array(33) [2, 134, 140, 186, 82, 70, 108, 182, 233, 40, 143, 247, 29, 76, 245, 206, 29, 87, 48, 7, 16 20 4 , 56, 236, 201, 80, 80, 152, 118, 92, 144, 48

s = String.fromCharCode.apply(null, a)

"oRFl?é(÷L??W0?Náò8ìéPPv\0"

"orFl?é(÷L??W0?Náò8ìéPPv\0"

回答by Dieghito

I found I had problems with this approach, basically because I was trying to write the output to a file and it was non encoded properly. Since JS seems to use UCS-2 encoding (source, source), we need to stretch this solution a step further, here's my enhanced solution that works to me.

我发现我对这种方法有问题,主要是因为我试图将输出写入文件并且没有正确编码。由于 JS 似乎使用 UCS-2 编码(sourcesource),我们需要进一步扩展这个解决方案,这是我的增强解决方案,对我有用。

I had no difficulties with generic text, but when it was down to Arab or Korean, the output file didn't have all the chars but instead was showing error characters

我对通用文本没有任何困难,但是当它归结为阿拉伯语或韩语时,输出文件没有所有字符,而是显示错误字符

File output:","10k unit":"",Follow:"??íüY?","Follow %{screen_name}":"%{screen_name}U“'??íü",Tweet:"?¤üè","Tweet %{hashtag}":"%{hashtag} '?¤üèY?","Tweet to %{name}":"%{name}U“x?¤üèY?"},ko:{"%{followers_count} followers":"%{followers_count}…X \ì","100K+":"100ì tá","10k unit":"ì è",Follow:"\°","Follow %{screen_name}":"%{screen_name} ? \°X0",K:"?",M:"1ì",Tweet:"?","Tweet %{hashtag}":"%{hashtag}

文件输出:","10k unit":"",Follow:"??íüY?","Follow %{screen_name}":"%{screen_name}U“'??íü",Tweet:"?¤üè","Tweet %{hashtag}":"%{hashtag} '?¤üèY?","Tweet to %{name}":"%{name}U“x?¤üèY?"},ko:{"%{followers_count} followers":"%{followers_count}…X \ì","100K+":"100ì tá","10k unit":"ì è",Follow:"\°","Follow %{screen_name}":"%{screen_name} ? \°X0",K:"?",M:"1ì",Tweet:"?","Tweet %{hashtag}":"%{hashtag}

Original:","10k unit":"万",Follow:"フォローする","Follow %{screen_name}":"%{screen_name}さんをフォロー",Tweet:"ツイート","Tweet %{hashtag}":"%{hashtag} をツイートする","Tweet to %{name}":"%{name}さんへツイートする"},ko:{"%{followers_count} followers":"%{followers_count}?? ???","100K+":"100? ??","10k unit":"? ??",Follow:"???","Follow %{screen_name}":"%{screen_name} ? ?????",K:"?",M:"??",Tweet:"??","Tweet %{hashtag}":"%{hashtag}

原来的:","10k unit":"万",Follow:"フォローする","Follow %{screen_name}":"%{screen_name}さんをフォロー",Tweet:"ツイート","Tweet %{hashtag}":"%{hashtag} をツイートする","Tweet to %{name}":"%{name}さんへツイートする"},ko:{"%{followers_count} followers":"%{followers_count}?? ???","100K+":"100? ??","10k unit":"? ??",Follow:"???","Follow %{screen_name}":"%{screen_name} ? ?????",K:"?",M:"??",Tweet:"??","Tweet %{hashtag}":"%{hashtag}

I took the information from dennis' solutionand this postI found.

我从丹尼斯的解决方案和我找到的这篇文章中获取了信息。

Here's my code:

这是我的代码:

function encode_utf8(s) {
  return unescape(encodeURIComponent(s));
}

function decode_utf8(s) {
  return decodeURIComponent(escape(s));
}

 function ab2str(buf) {
   var s = String.fromCharCode.apply(null, new Uint8Array(buf));
   return decode_utf8(decode_utf8(s))
 }

function str2ab(str) {
   var s = encode_utf8(str)
   var buf = new ArrayBuffer(s.length); 
   var bufView = new Uint8Array(buf);
   for (var i=0, strLen=s.length; i<strLen; i++) {
     bufView[i] = s.charCodeAt(i);
   }
   return bufView;
 }

This allows me to save the content to a file without encoding problems.

这使我可以将内容保存到文件中而不会出现编码问题。

How it works: It basically takes the single 8-byte chunks composing a UTF-8 character and saves them as single characters (therefore an UTF-8 character built in this way, could be composed by 1-4 of these characters). UTF-8 encodes characters in a format that variates from 1 to 4 bytes in length. What we do here is encoding the sting in an URI component and then take this component and translate it in the corresponding 8 byte character. In this way we don't lose the information given by UTF8 characters that are more than 1 byte long.

工作原理:它基本上采用组成 UTF-8 字符的单个 8 字节块并将它们保存为单个字符(因此以这种方式构建的 UTF-8 字符可以由这些字符中的 1-4 个组成)。UTF-8 以长度从 1 到 4 个字节的格式对字符进行编码。我们在这里做的是在 URI 组件中对 sting 进行编码,然后获取该组件并将其转换为相应的 8 字节字符。这样我们就不会丢失超过 1 个字节长的 UTF8 字符给出的信息。