我有一个javascript字符串,当以UTF-8从服务器发送时,它的大小约为500K。如何在JavaScript中确定它的大小?
我知道JavaScript使用UCS-2,所以每个字符占2个字节。但是,这是否取决于JavaScript的实现方式?还是取决于页面编码或内容类型?
我有一个javascript字符串,当以UTF-8从服务器发送时,它的大小约为500K。如何在JavaScript中确定它的大小?
我知道JavaScript使用UCS-2,所以每个字符占2个字节。但是,这是否取决于JavaScript的实现方式?还是取决于页面编码或内容类型?
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://dev59.com/JnE95IYBdhLWcg3wp_kg#39488643
new Blob([String.fromCharCode(55555)]).size, // 3
new Blob([String.fromCharCode(55555, 57000)]).size // 4 (not 6)
);
Buffer.from('').length
。 - Alexander Mills.split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./)
代替。您的代码片段无法正确处理编码为“%uXXXX”格式的字符串。 - Rob W如果你正在使用 node.js,可以使用 buffers 来实现更简单的解决方案:
function getBinarySize(string) {
return Buffer.byteLength(string, 'utf8');
}
有一个npm库可以实现这个功能:https://www.npmjs.org/package/utf8-binary-cutter(来自您真诚的)
5
用于 "\x80\u3042"
,而 Ruby 的 bytesize
返回 4
(请参阅 https://apidock.com/ruby/String/bytesize)。 - Micael LeviString
值不受实现的影响,根据ECMA-262第三版规格说明,每个字符代表着UTF-16文本的一个单一的16位单元:
4.3.16 字符串值
字符串值是String类型的成员,是一个有限的、有序的零或多个16位无符号整数值的序列。
注意:尽管每个值通常表示UTF-16文本的一个单一的16位单元,但语言并未对这些值作出任何限制或要求,除了必须是16位无符号整数。
以下是我使用的三种方式:
TextEncoder
new TextEncoder().encode("myString").length
Blob
new Blob(["myString"]).size
缓冲区
Buffer.byteLength("myString", 'utf8')
TextEncoder
选项快了6倍以上:https://i.ibb.co/QkfsJQN/Screenshot-from-2020-12-20-16-29-27.png - Saiansh Singh尝试使用 unescape JavaScript 函数的这种组合:
const byteAmount = unescape(encodeURIComponent(yourString)).length
完整的编码过程示例:
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
unescape
е‡Ңж•°е·Із»Џиұ«еәѓз”ЁпәЊдёҚеғ”иҮӨз”ЁдғҺи§Әз Ѓз»џдёЂиµ„жғђж ‡иҮ†з¬¦пә€URIпә‰гЂ‚жқӨжғђ - Lauri Oherdunescape
没有被用来解码URI。它被用来将%xx
序列转换为单个字符。由于encodeURIComponent
将字符串编码为UTF-8,表示代码单元作为其对应的ASCII字符或%xx
序列,调用unescape(encodeURIComponent(...))
会得到一个二进制字符串,其中包含原始字符串的UTF-8表示。调用.length
可以正确地给出以UTF-8编码的字符串的字节大小。 - T Sun
escape
已被弃用,但它仍然在每个浏览器中可用... - 也就是说,有很好的理由将其弃用。基本上没有正确使用它们的方法(除了与en
-/decodeURI
(Component
)结合使用对UTF8进行编码/解码之外-或者至少我不知道其他有用的应用程序(un
)escape
)。今天有更好的替代方案来编码/解码UTF8(TextEncoder
等)。 - T S请注意,如果你的目标是node.js,你可以使用Buffer.from(string).length
:
var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
ES6之前
始终为每个字符2字节。不允许使用UTF-16,因为规范中说“值必须是16位无符号整数”。由于UTF-16字符串可以使用3个或4个字节的字符,这将违反2字节要求。关键是,虽然不能完全支持UTF-16,但标准确实要求使用的两个字节字符是有效的UTF-16字符。换句话说,ES6之前的JavaScript字符串支持UTF-16字符的子集。
ES6及其后续版本
每个字符2个字节,或每个字符5个或更多字节。额外的大小是因为ES6(ECMAScript 6)添加了对Unicode代码点转义的支持。使用Unicode转义如下:\u{1D306}
实用笔记
这与特定引擎的内部实现无关。例如,某些引擎使用具有完全UTF-16支持的数据结构和库,但它们提供的外部内容不必是完全的UTF-16支持。此外,引擎也可以提供外部UTF-16支持,但不一定要这样做。
对于ES6,实际上字符永远不会超过5个字节(2个字节用于转义点+3个字节用于Unicode代码点),因为最新版本的Unicode只有136,755个可能的字符,可以轻松地容纳在3个字节中。但是,从技术上讲,这不受标准的限制,因此一个单一字符可以使用4个字节的代码点和6个字节的总长度。
这里大多数计算字节大小的代码示例似乎没有考虑到ES6 Unicode代码点转义,因此在某些情况下结果可能不正确。
Buffer.from('test').length
和Buffer.byteLength('test')
以及new Blob(['test']).size
都等于4? - user1063287'\u{1F600}'.length===2
,'\u{1F600}'==='\uD83D\uDE00'
,`'\u{1F600}'==='') - T SUTF-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;
}
示例:
getStringMemorySize( 'I' ); // 2
getStringMemorySize( '❤' ); // 4
getStringMemorySize( '' ); // 8
getStringMemorySize( 'I❤' ); // 14
byteCount(String.fromCharCode(55555))
// URIError: URI malformed
这个较长的函数应该处理所有字符串:
function bytes (str) {
var bytes=0, len=str.length, codePoint, next, i;
for (i=0; i < len; i++) {
codePoint = str.charCodeAt(i);
// Lone surrogates cannot be passed to encodeURI
if (codePoint >= 0xD800 && codePoint < 0xE000) {
if (codePoint < 0xDC00 && i + 1 < len) {
next = str.charCodeAt(i + 1);
if (next >= 0xDC00 && next < 0xE000) {
bytes += 4;
i++;
continue;
}
}
}
bytes += (codePoint < 0x80 ? 1 : (codePoint < 0x800 ? 2 : 3));
}
return bytes;
}
例如
bytes(String.fromCharCode(55555))
// 3
bytes(String.fromCharCode(55555, 57000))
// 4 (not 6)
Buffer.byteLength
进行比较:Buffer.byteLength(String.fromCharCode(55555), 'utf8')
// 3
Buffer.byteLength(String.fromCharCode(55555, 57000), 'utf8')
// 4 (not 6)