前置知识
字节
字节(Byte)是计算机信息技术用于计量存储容量的一种计量单位,也表示一些计算机编程语言中的数据类型和语言字符。
- 一个字节(byte)8位(bit),十进制表示0~255。
- 两个字节16位,可表示十进制0~65535。
Unicode字符集
Unicode 做了一件事,就是给世界上所有字符都分配了一个唯一的数字编号,这个编号范围从0x000000~0x10FFFF,包括110多万。但大部分常用字符都在0x0000~0xFFFF之间,即65536个数字之内。每个字符都有一个Unicode编号,这个编号一般写成十六进制,在前面加U+。编号怎么对应到二进制表示呢?有多种方案,主要有UTF-32、UTF-16和UTF-8。
JavaScript 使用 Unicode 字符集,采用 UTF-16 编码方案(整合UCS-2编码。一开始JavaScript采用的是UCS-2,那时候Unicode的UTF-16标准还没发布)。UTF-16兼容ASCII,即前128个Unicode代码点是ASCII字符编码的直接匹配。
各字符集中汉字所占字节
- ASCii字符集:只有英文、数字、符号等,占1个字节。
- GBK字符集:汉字占2个字节,英文、数字占1个字节。
- UTF-32字符集:汉字占4个字节,英文、数字占2个字节。
- UTF-8字符集:汉字占3个字节,英文、数字占1个字节。
数据库中字段长度
- Oracle- Oracle中varchar2类型的字段长度单位默认是按照byte(字节)来定义,比如常见写法varchar2(10)代表只接收最大10字节长度。- 其实我们在Oracle中也可以用字符为单位来定义varchar2字段的长度,这个时候需要注意在建表时写成VARCHAR2(10 char)。
- MySql- 5.X 以上的版本的定义中表示的字符长度,如上varchar(20)你既可以添加20个英文字符,也可以添加二十个中文字符。- 4.X 的版本表示的是字节长度,会根据字符集转变内容字节长度存储。
- 使用oracle数据库或mysql4.x数据库,就需要注意所提交字符(串)的字节长度。
方法charCodeAt
charCodeAt()方法返回 0 到 65535 之间的整数,表示给定索引处的 UTF-16 代码单元(小知识:2的16次方等于65536)。
有些网友说返回的是十六进制的整数,我们可以进行如下测试验证一下:
var str ="编码"
console.log('测试数据 = '+ str.charAt(0))
console.log('------------------- ')
console.log('情况一:charCodeAt返回的是16进制的unicode编码')//十六进制var code16 = str.charCodeAt(0)
console.log('十六进制编码 = '+ code16)// 使用eval(),将十六进制的unicode编码转换为字符var res =eval("'\\u"+ code16 +"'")
console.log('恢复成字符 = '+ res+";测试"+(res == str.charAt(0)?"通过✅":"不通过❌"))
console.log('------------------- ')
console.log('情况一:charCodeAt返回的是10进制的unicode编码')//十进制var code10 = str.charCodeAt(0)
console.log('十进制编码 = '+ code10)
console.log('十六进制编码 = '+ code10.toString(16))// 使用eval(),将十六进制的unicode编码转换为字符var res2 =eval("'\\u"+ code10.toString(16)+"'")
console.log('恢复成字符 = '+ res2+";测试"+(res2 == str.charAt(0)?"通过✅":"不通过❌"))
console.log('------------------- ')
测试数据 = 编
-------------------
情况一:charCodeAt返回的是16进制的unicode编码
十六进制编码 =32534
恢复成字符 = ㉓4;测试不通过❌
-------------------
情况一:charCodeAt返回的是10进制的unicode编码
十进制编码 =32534
十六进制编码 = 7f16
恢复成字符 = 编;测试通过✅
-------------------
测试结果表明,返回的是十进制的整数。
字符串(字节)长度计算
需求:前端向后端提交数据,数据库字段限制了长度,一般单位是字节,中英文字符所占字节数是不一样的。所以对于中英文混合的数据不能直接使用字符串的length属性来获取长度(字符个数)。
思路:
- 要明确后端数据库所采用的字符集,再计算数据提交到数据库后实际所占的字节长度(是否符合数据库字段所限制长度)。
- 使用方法charCodeAt(),获取字符的unicode编码(0 到 65535 之间的整数)。
- 常见英文字母、英文标点符号(半角符号),unicode编码小于128(0~127。1字节可表示0~255),即ASCII编码。
- 判断方法charCodeAt()返回的整数是否大于255(0开始),若大于则认为是汉字字符。也有网友通过判断unicode编码是否大于127作为分界。
/**
* 获取字节长度。
* ASCii字符集:只有英文、数字、符号等,占1个字节。
* GBK字符集:汉字占2个字节,英文、数字占1个字节。
* UTF-32字符集:汉字占4个字节,英文、数字占2个字节。
* UTF-8字符集:汉字占3个字节,英文、数字占1个字节。
*/functiongetByteLen(value, charset){var charlen =2;//默认 1个汉字占2字节if(!charset){
charset ='gbk';//默认为gbk(数据库中最常用的字符集是utf-8、gbk)}if((charset +"").toLowerCase().indexOf('gb')==0){//GB2312、GBK、GB18030
charlen =2;}if((charset +"").toLowerCase()=='utf-8'){
charlen =3;}if((charset +"").toLowerCase()=='utf-32'){
charlen =4;}if(value ==null|| value.length <1)return0;var len =0;for(var i =0; i < value.length; i++){if(value.charCodeAt(i)<255){
len++;}else{
len += charlen;}}return len;}
示例:
console.log(getByteLen('ab我','utf-8'));//5
console.log(getByteLen('ab我','gbk'));//4
console.log(getByteLen('ab我'));//4
扩展
实现字符与unicode编码互转,见这篇博客。
参考:CSDN、脚本之家、百度百科、《Java编程的逻辑》-马俊昌
版权归原作者 轻率的保罗 所有, 如有侵权,请联系我们删除。