字符串(字节)长度计算
·
前置知识
字节
字节(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个字节。
*/
function getByteLen(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) return 0;
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编码互转,见这篇博客。
更多推荐
已为社区贡献2条内容
所有评论(0)