JavaScript 中的字符串长度(以字节为单位)

2022-08-30 02:13:51

在我的JavaScript代码中,我需要以这种格式编写一条消息到服务器:

<size in bytes>CRLF
<data>CRLF

例:

3
foo

数据可能包含 Unicode 字符。我需要将它们作为 UTF-8 发送。

我正在寻找在JavaScript中以字节为单位计算字符串长度的最跨浏览器方法。

我已经尝试过这个来组成我的有效负载:

return unescape(encodeURIComponent(str)).length + "\n" + str + "\n"

但是它并没有为我提供旧版浏览器的准确结果(或者,也许是UTF-16中这些浏览器中的字符串?)。

有什么线索吗?

更新:

示例:UTF-8 中字符串的长度(以字节为单位)为 15 个字节,但某些浏览器报告的字节数为 23 个字节。ЭЭХ! Naïve?


答案 1

几年过去了,现在你可以本地做到这一点

(new TextEncoder().encode('foo')).length

请注意,IE不支持它(您可以使用polyfill)。

MDN 文档

标准规格


答案 2

在 JavaScript 中,没有办法在 JavaScript 中本地做到这一点。(参见Riccardo Galli的答案,了解现代方法。


用于历史参考或文本编码器 API 仍然不可用的地方。

如果您知道字符编码,则可以自己计算。

encodeURIComponent假设 UTF-8 作为字符编码,所以如果你需要该编码,你可以这样做,

function lengthInUtf8Bytes(str) {
  // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
  var m = encodeURIComponent(str).match(/%[89ABab]/g);
  return str.length + (m ? m.length : 0);
}

这应该有效,因为 UTF-8 编码多字节序列的方式。对于单个字节序列,第一个编码字节始终以高位零开头,或者以第一个十六进制数字为 C、D、E 或 F 的字节开头。第二个和后续字节是前两个位为 10 的字节。这些是您要以 UTF-8 计算的额外字节。

维基百科中的表格使其更清晰

Bits        Last code point Byte 1          Byte 2          Byte 3
  7         U+007F          0xxxxxxx
 11         U+07FF          110xxxxx        10xxxxxx
 16         U+FFFF          1110xxxx        10xxxxxx        10xxxxxx
...

相反,如果您需要了解页面编码,则可以使用以下技巧:

function lengthInPageEncoding(s) {
  var a = document.createElement('A');
  a.href = '#' + s;
  var sEncoded = a.href;
  sEncoded = sEncoded.substring(sEncoded.indexOf('#') + 1);
  var m = sEncoded.match(/%[0-9a-f]{2}/g);
  return sEncoded.length - (m ? m.length * 2 : 0);
}