JavaScript中的字符串长度(字节)

JavaScript中的字符串长度(字节),javascript,unicode,Javascript,Unicode,在我的JavaScript代码中,我需要以以下格式向服务器发送消息: <size in bytes>CRLF <data>CRLF 数据可能包含unicode字符。我需要以UTF-8的形式发送它们 我正在寻找最跨浏览器的方法来计算JavaScript中字符串的长度(以字节为单位) 我尝试了以下方法来组合我的有效负载: return unescape(encodeURIComponent(str)).length + "\n" + str + "\n" 但是对于旧的浏览

在我的JavaScript代码中,我需要以以下格式向服务器发送消息:

<size in bytes>CRLF
<data>CRLF
数据可能包含unicode字符。我需要以UTF-8的形式发送它们

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

我尝试了以下方法来组合我的有效负载:

return unescape(encodeURIComponent(str)).length + "\n" + str + "\n"
但是对于旧的浏览器(或者UTF-16中那些浏览器中的字符串?),它并没有给出准确的结果

有什么线索吗

更新:

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

在JavaScript中无法以本机方式实现这一点。(有关现代方法,请参见。)


用于历史参考或TextEncoder 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);
}

事实上,我知道怎么了。要使代码正常工作,页面
应具有以下标签:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

注意:我怀疑指定任何(准确的)编码都可以解决编码问题。恰好我需要UTF-8。

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

函数字节数{
返回encodeURI.split(/%.../).length-1;
}
您可以尝试以下方法:

function getLengthInBytes(str) {
  var b = str.match(/[^\x00-\xff]/g);
  return (str.length + (!b ? 0: b.length)); 
}

它适合我。

这里有一个更快的版本,它不使用正则表达式,也不使用:

远程通信功能(str){
//返回utf8字符串的字节长度
var s=str.length;
对于(变量i=str.length-1;i>=0;i--){
var代码=str.charCodeAt(i);

如果(代码>0x7f&&code 0x7ff&&code=0xDC00&&code年过去了,现在您可以以本机方式执行此操作

(new TextEncoder().encode('foo')).length
请注意,IE不支持它(您可能会对此感到遗憾)


这里有一个独立而有效的方法来计算字符串的UTF-8字节数

//计算字符串的UTF-8字节
通过TELENGTHOF(s)实现的功能{
//假设字符串是UCS-2(又称UTF-16)编码的
var n=0;

对于(var i=0,l=s.length;i这将适用于BMP和SIP/SMP字符

    String.prototype.lengthInUtf8 = function() {
        var asciiLength = this.match(/[\u0000-\u007f]/g) ? this.match(/[\u0000-\u007f]/g).length : 0;
        var multiByteLength = encodeURI(this.replace(/[\u0000-\u007f]/g)).match(/%/g) ? encodeURI(this.replace(/[\u0000-\u007f]/g, '')).match(/%/g).length : 0;
        return asciiLength + multiByteLength;
    }

    'test'.lengthInUtf8();
    // returns 4
    '\u{2f894}'.lengthInUtf8();
    // returns 4
    'سلام علیکم'.lengthInUtf8();
    // returns 19, each Arabic/Persian alphabet character takes 2 bytes. 
    '你好,JavaScript 世界'.lengthInUtf8();
    // returns 26, each Chinese character/punctuation takes 3 bytes. 

对于简单的UTF-8编码,Blob的兼容性略优于
textcoder
,但在非常旧的浏览器中不起作用

new Blob(["Another very simple approach using 
Buffer
(only for NodeJS):

Buffer.byteLength(string, 'utf8')

Buffer.from(string).length

新Blob([“另一种使用
缓冲区的非常简单的方法(仅适用于NodeJ):


我花了一些时间找到了React Native的解决方案,因此我将其放在这里:

首先安装
缓冲区
软件包:

const { Buffer } = require('buffer');
const length = Buffer.byteLength(string, 'utf-8');
然后使用节点方法:

let strLengthInBytes = Buffer.byteLength(str); // str is UTF-8
在NodeJS中,是一种专门用于此目的的方法:


请注意,默认情况下,该方法假定字符串采用UTF-8编码。如果需要不同的编码,请将其作为第二个参数传递。

为了提高速度,我比较了Firefox中建议的一些方法

我使用的字符串包含以下字符: 遇到这个

其中字符串与前面的答案不匹配

我在这里得到了8的预期长度:

const str='X";FUEL";'
const div=document.createElement(“div”);
div.innerHTML=str

console.log(div.textContent.length)
可能重复?@Eli:你链接的问题中没有一个答案适合我。当你谈论“èèèèèèèèèèèèèèè”时,你是否将其转换为特定的正常形式?@mi并保存了它。就像我的库的任何用户都会做的那样。然而,似乎我发现了什么是错误的-请看我的答案。那么,我怎么知道数据的字符编码呢?我需要编码任何字符串用户(程序员)提供给我的JS库。@Alexander,当您将消息发送到服务器时,是否通过HTTP头指定消息正文的内容编码?@Alexander,很酷。如果要建立协议,强制使用UTF-8是文本交换的好主意。少一个可能导致不匹配的变量。UTF-8应该是netwo字符编码的rk字节顺序。@MikeSamuel:
lengthInUtf8Bytes
函数对非BMP字符返回5,对这些返回返回2('
unescape
JavaScript函数可用于解码统一资源标识符(URI)。@LauriOherd
unescape
确实不应用于解码URI。但是,要将文本转换为UTF-8,它可以工作
unescape(encodeURIComponent(…).length
始终计算正确的长度,无论是否使用
meta http equiv…utf8
。如果没有编码规范,某些浏览器可能只是有不同的文本(将文档字节编码为实际html文本后)他们计算了其长度。通过不仅打印长度,而且打印文本本身,可以很容易地对此进行测试。@LauriOherd是的,并且在本例中它不用于解码URI。这是一个得到广泛支持的解决方案,具有良好的性能:这是一个多么奇妙、现代的方法。谢谢!请注意,根据Safari(WebKit)发布的ted。自Chrome 53以来,ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted ted仅支持utf-8。如果您只需要长度,分配一个新字符串可能有点过火,请进行实际转换,然后
new Blob(["Another very simple approach using 
Buffer
(only for NodeJS):

Buffer.byteLength(string, 'utf8')

Buffer.from(string).length
npm install --save buffer
const { Buffer } = require('buffer');
const length = Buffer.byteLength(string, 'utf-8');
let strLengthInBytes = Buffer.byteLength(str); // str is UTF-8