使用 TextEncoder 获取字符串的字节数
之前有同事因为一段文本超出规定字节数,询问过我,怎么知道一段文字有多少个字节。
当时只是简单的回他一般英文与数字每个字符占一个字节,而中文字符占多少个字节需要根据字符编码来判断。比如中国的GBK/GB2312/GB18030等,一个中文字符就是两个字节;而现在主流的编码方式UTF-8中,一个中文字符则是三个字节。
TextEncoder
后来无意中在 MDN 里看到这么一个方法,可以将一段文本字符生成采用UTF-8编码的字节流(它还有一个作用相反的配套方法 TextDecoder)。如此很简单的一个查询字符串字节数的方法就出来了。
1 | const encoder = new TextEncoder(); |
原本 TextEncoder 还应该有一个参数 encoding,可以指定编码,但是因为标准规定 encoding 始终返回 “utf-8”,所以只能获取到UTF-8编码下的字符串的字节数。
不过 GitHub 上倒是有一个polyfill支持非utf-8的编码。
1 | const enc = new TextEncoder('gbk'); |
后续
String.property.codePointAt/String.fromCodePoint
随着查询字符编码,还让我了解了一个字符串的方法 String.property.codePointAt
。
这个方法的作用类似于 String.property.charCodeAt
,都是返回字符串某一位置的字符代码点的值,用法也和 String.property.charCodeAt
一样。
1 | var str = '笑一笑😀'; |
那么它们的区别是什么?这里就要说到四字节的字符了。
我们平时使用的Unicode编码字符,都是 U+0000 - U+FFFF 来标识的。而 U+FFFF 则是三字节能表示的最大字符数了,那么四字节要怎么标识呢?答案是用两个Unicode字符来标识,比如上面的笑脸emoji😀,它的Unicode编码其实是 \ud83d\ude00
,而且其长度为2。
1 | '😀'.length === 2; // true |
像这样用两个Unicode字符来标识的四字节字符,是无法使用 String.property.charCodeAt
来获取其完整代码点的,该方法只能获取到一个Unicode代码单元的代码点,即String.property.charCodeAt
只能获取一个长度的Unicode的字符代码点。
而要获取这种四字节字符的完整代码点,则要使用 String.property.codePointAt
。
1 | var str = '笑一笑😀'; |
就如同 String.property.charCodeAt
有一个对应的方法 String.fromCharCode
,String.property.codePointAt
也有一个对应的从代码点得到对应字符的方法 String.fromCodePoint
。
1 | String.fromCodePoint(128512); // 😀 |
参考链接
- TextEncoder
- TextDecoder
- String.property.codePointAt
- String.property.charCodeAt
- 中文汉字占二个字节还是三个字节长度