2种常用方法
以下2种方法,只针对UTF-8编码,详细原因 请见后文的 关于编码。
// 方法1
function calculateUtf8ByteSize(str) {// 非字符串 不作计算if (typeof str !== 'string') return;// 定义变量,用于累加字节数let byteCount = 0;// 遍历字符串中的每个字符for (let i = 0, len = str.length; i < len; i++) {// 获取当前字符的Unicode码const charCode = str.charCodeAt(i);// 根据字符的Unicode码,计算其占用的字节数if (charCode <= 0x007F) {byteCount += 1; // 在000000-00007F之间的字符(如字母),占用1个字节} else if (charCode <= 0x07FF) {byteCount += 2; // 在000080-0007FF之间的字符(如中文),占用2个字节} else if (charCode <= 0xFFFF) {byteCount += 3; // 000800-00FFFF之间的字符(如中文),占用3个字节} else if (charCode <= 0x10FFFF){byteCount += 4; // 010000-10FFFF之间的字符(如表情),占用4个字节} else {console.log('该字符超出Unicode编码范围');}}return byteCount;
}
// 方法2
function calculateUtf8ByteSize(str) {// 非字符串 不作计算if (typeof str !== 'string') return;// 创建一个TextEncoder实例const encoder = new TextEncoder();// 将字符串转换为UTF8编码的字节流(即Uint8Array数据)const utf8 = encoder.encode(str);return utf8.length;
}
注意:方法2代码量虽少,但其中的TextEncoder,在低版本浏览器可能存在兼容问题。
关于编码
ASCII编码
由美国制定的一套字符集,也是一种编码方式,主要用于英语环境,对应了英文字母、数字、特殊字符和控制字符 等等,它规定1个字符只占用1个字节。
Unicode字符
对应全世界语言符号的一套字符集(且都是唯一的),适用于全球环境(因此也称为万国码),但没有定义 1个字符占用多少字节。
UTF-16编码
一种编码方式,用于将 Unicode字符 编码为可存储的字节。这种编码方式规定,1个Unicode字符占用2或4个字节(绝大多数是2个字节),且无法兼容ASCII码。由于其占用固定的字节数,因此对内存会造成一定的浪费。
UTF-8编码
一种编码方式,用于将 Unicode字符 编码为可存储的字节。这种编码方式规定,1个Unicode字符占用1~4个字节(如上文JS代码所示),可兼容ASCII码。由于其使用更合理的内存分配,因此内存占用比UTF-16更小。
1)字符集 和 编码
Unicode仅仅是一套字符集,并非编码,因为它没有定义 每个字符在计算机中的存储方式(即占用多少字节),而ASCII、UTF-8、UTF-16才算是编码。
2)为何常听说“每个unicode字符占2个字节”
这种说法是不准确的。由于系统前期大多使用UTF-16对Unicode字符进行编码,加上绝大多数情况下的字符只占用2个字符,因此才传出这种说法。