JavaScript字符串中有多少字节?

Pau*_*gar 78 javascript string size byte

我有一个javascript字符串,当从UTF-8服务器发送时,大约500K.如何在JavaScript中说出它的大小?

我知道JavaScript使用UCS-2,所以这意味着每个字符2个字节.但是,它是否依赖于JavaScript实现?或者在页面编码或内容类型?

Lau*_*erd 64

此函数将返回传递给它的任何UTF-8字符串的字节大小.

function byteCount(s) {
    return encodeURI(s).split(/%..|./).length - 1;
}
Run Code Online (Sandbox Code Playgroud)

资源

JavaScript引擎可以在内部免费使用UCS-2或UTF-16.我所知道的大多数引擎都使用UTF-16,但无论做出什么选择,它只是一个不会影响语言特性的实现细节.

但是,ECMAScript/JavaScript语言本身根据UCS-2而不是UTF-16公开字符.

资源

  • 使用`.split(/%(?:u [0-9A-F] {2})?[0-9A-F] {2} | ./)`代替.对于编码为"%uXXXX"的字符串,您的代码段失败. (7认同)
  • 用于上传到s3的javascript字符串,s3显示完全相同的大小[(byteCount(s))/ 1024).toFixed(2)+"KiB"] (2认同)

Off*_*rmo 41

如果您正在使用node.js,则使用缓冲区有一个更简单的解决方案:

function getBinarySize(string) {
    return Buffer.byteLength(string, 'utf8');
}
Run Code Online (Sandbox Code Playgroud)

有一个npm lib:https://www.npmjs.org/package/utf8-binary-cutter(来自你的忠实)


CMS*_*CMS 30

String值不依赖于实现,根据ECMA-262第3版规范,每个字符代表一个16位单位的UTF-16文本:

4.3.16字符串值

字符串值是String类型的成员,是零个或多个16位无符号整数值的有限有序序列.

注意虽然每个值通常表示单个16位UTF-16文本单元,但该语言不会对值赋予任何限制或要求,除非它们是16位无符号整数.

  • 我对该段落的解读并不意味着实现独立性. (7认同)
  • UTF-16不保证,只有字符串存储为16位整数的事实. (4认同)

P R*_*tto 24

您可以使用Blob以字节为单位获取字符串大小.

例子:

console.info(
  new Blob(['']).size,                             // 4
  new Blob(['']).size,                             // 4
  new Blob(['']).size,                           // 8
  new Blob(['']).size,                           // 8
  new Blob(['I\'m a string']).size,                  // 12

  // from Premasagar correction of Lauri's answer for
  // strings containing lone characters in the surrogate pair range:
  // https://stackoverflow.com/a/39488643/6225838
  new Blob([String.fromCharCode(55555)]).size,       // 3
  new Blob([String.fromCharCode(55555, 57000)]).size // 4 (not 6)
);
Run Code Online (Sandbox Code Playgroud)

  • 感谢上帝的斑点!这应该是现代浏览器公认的答案。 (3认同)
  • 嗯,在Node.js中,我们使用Buffer,例如`Buffer.from('')。length` (2认同)
  • Blob 现已内置于 NodeJS v18 中 (2认同)

Kin*_*iro 19

使用unescape js函数尝试此组合:

const s  = "1 a ? ? @ ®"; //length is 11
const s2 = encodeURIComponent(s); //length is 41
const s3 = unescape(s2); //length is 15 [1-1,a-1,?-2,?-3,@-1,®-2]
const s4 = escape(s3); //length is 39
const s5 = decodeURIComponent(s4); //length is 11
Run Code Online (Sandbox Code Playgroud)

完整编码过程示例:

const s  = "1 a ? ? @ ®"; //length is 11
const s2 = encodeURIComponent(s); //length is 41
const s3 = unescape(s2); //length is 15 [1-1,a-1,?-2,?-3,@-1,®-2]
const s4 = escape(s3); //length is 39
const s5 = decodeURIComponent(s4); //length is 11
Run Code Online (Sandbox Code Playgroud)

请参阅aditional屏幕 http://dl.dropbox.com/u/2086213/%3Dcoding%3D/js_utf_byte_length.png (我是新用户,因此我无法使用img标签)

  • 不推荐使用`unescape` JavaScript函数,不应该使用它来解码统一资源标识符(URI).[来源](http://msdn.microsoft.com/en-us/library/dz4x90hk(V = vs.94)的.aspx) (4认同)

小智 15

这些是我使用的 3 种方式:

  1. TextEncoder
new TextEncoder().encode("myString").length
Run Code Online (Sandbox Code Playgroud)
  1. Blob
new Blob(["myString"]).size
Run Code Online (Sandbox Code Playgroud)
  1. Buffer
Buffer.byteLength("myString", 'utf8')
Run Code Online (Sandbox Code Playgroud)

  • 似乎“TextEncoder”选项的速度快了 6 倍以上:https://i.ibb.co/QkfsJQN/Screenshot-from-2020-12-20-16-29-27.png (2认同)

mae*_*ics 9

请注意,如果您的目标是node.js,则可以使用Buffer.from(string).length:

var str = "\u2620"; // => "?"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
Run Code Online (Sandbox Code Playgroud)


whi*_*and 7

JavaScript 字符串的大小是

  • ES6 之前:每个字符 2 个字节
  • ES6及更高版本:每个字符 2 个字节,或每个字符 5 个或更多字节

ES6 之前的
每个字符始终为 2 个字节。UTF-16 是不允许的,因为规范说“值必须是 16 位无符号整数”。由于 UTF-16 字符串可以使用 3 或 4 字节字符,因此会违反 2 字节要求。至关重要的是,虽然不能完全支持 UTF-16,但标准确实要求使用的两个字节字符是有效的 UTF-16 字符。换句话说,Pre-ES6 JavaScript 字符串支持 UTF-16 字符的子集。

ES6 及更高版本
每个字符 2 个字节,或每个字符 5 个或更多字节。因为 ES6 (ECMAScript 6) 添加了对Unicode 代码点转义的支持,所以额外的大小开始发挥作用。使用 unicode 转义看起来像这样:\u{1D306}

实用笔记

  • 这与特定引擎的内部实现无关。例如,一些引擎使用完全支持 UTF-16 的数据结构和库,但它们外部提供的内容不一定是完全支持 UTF-16。此外,引擎也可以提供外部 UTF-16 支持,但并非强制要求这样做。

  • 对于 ES6,实际上字符的长度永远不会超过 5 个字节(转义点为 2 个字节 + Unicode 代码点为 3 个字节),因为最新版本的 Unicode 只有 136,755 个可能的字符,这很容易放入 3 个字节。然而,这在技术上不受标准的限制,因此原则上可以使用单个字符,例如 4 个字节用于代码点,总共 6 个字节。

  • 这里用于计算字节大小的大多数代码示例似乎没有考虑 ES6 Unicode 代码点转义,因此在某些情况下结果可能不正确。

  • 只是想知道,如果每个字符的大小为 2 个字节,为什么 `Buffer.from('test').length` 和 `Buffer.byteLength('test')` 等于 4(在 Node 中)和 `new Blob(['test ']).size` 也等于 4? (2认同)

Mac*_*Mac 6

UTF-8使用每个代码点1到4个字节对字符进行编码.正如CMS在接受的答案中指出的那样,JavaScript将使用16位(2字节)在内部存储每个字符.

如果通过循环解析字符串中的每个字符并计算每个代码点使用的字节数,然后将总计数乘以2,则应该具有该UTF-8编码字符串的JavaScript内存使用量(以字节为单位).也许是这样的:

      getStringMemorySize = function( _string ) {
        "use strict";

        var codePoint
            , accum = 0
        ;

        for( var stringIndex = 0, endOfString = _string.length; stringIndex < endOfString; stringIndex++ ) {
            codePoint = _string.charCodeAt( stringIndex );

            if( codePoint < 0x100 ) {
                accum += 1;
                continue;
            }

            if( codePoint < 0x10000 ) {
                accum += 2;
                continue;
            }

            if( codePoint < 0x1000000 ) {
                accum += 3;
            } else {
                accum += 4;
            }
        }

        return accum * 2;
    }
Run Code Online (Sandbox Code Playgroud)

例子:

getStringMemorySize( 'I'    );     //  2
getStringMemorySize( '?'    );     //  4
getStringMemorySize( ''   );     //  8
getStringMemorySize( 'I?' );     // 14
Run Code Online (Sandbox Code Playgroud)