目标:
- 了解编码相关概念
- 为什么emoji显示不正常
- 怎么解析emoji
问题:
- 什么是 ASCII?
- 为什么一个字节是8位数?
- 什么是unicode编码?
- 什么是UTF8编码?
- 为什么会产生乱码?
- emoji 编码
- 为什么emoji显示不正常?
- 计算emoji的码点
1. 什么是ASCII?
ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符。
2. 为什么一个字节是8位数?
60年代IBM的System/360用EBCDIC编码,ASCII编码标准也是在那个时候确立,两种标准虽然有差异,但都用8个bit来表示一个字符,
3. 什么是unicode编码?
ASCII 编码的局限, 导致各个国家只能开发自己的编码规范。
如果要表示中文,显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
为了统一所有文字的编码,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
所有 Unicode 🈶被称为 统一码、万国码、单一码
unicode 是一套编码方案。
4. 什么是UTF8编码?
UTF8 是unicode编码方案的具体实现
做的事情就是规定码点是怎么存储的。
同样的 还有 UTF16,UTF32
UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8最多可用到6个字节。
如表:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
5. 为什么会产生乱码?
笑脸:😁
码点:U+1F600
在线编码转换:http://tool.oschina.net/hexconvert/
二进制: 11111011000000000
UTF8:
码点:11111 011000 000000
UTF8编码规范:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
实际存储数值:1110000100111111001100010000000
实际存储数值16进制:0x709f9880
6. emoji 编码
emoji 是 Unicode 编码的一部分
-
杂项符号及图形
杂项符号及图形一共有768个字符,范围为: U+1F300 ~ U+1F5FF
-
增补符号及图形
增补符号及图形中一共有82个字符,范围为: U+1F900 ~ U+1F9FF
-
表情符号
表情符号一共有80个字符,范围为: U+1F600 ~ U+1F64F
-
交通及地图符号
交通及地图符号一共有103个字符,范围为: U+1F680 ~ U+1F6FF
-
杂项符号
杂项符号一共有256个字符,范围为: U+2600 ~ U+26FF 或拼上 U+FE0F
-
封闭式字母数字符号
-
封闭式字母数字补充符号
-
......
-
还有很多,不一一列出 参考: 《Emojis in Javascript》 https://medium.com/@thekevinscott/emojis-in-javascript-f693d0eb79fb#.o29wt8xei
7. 为什么emoji显示不正常?
既然emoji在unicode 分配了唯一的编码, 实际上跟文字已经没有任何区别, 而显示为一个框框,就是因为字体,在对应的码点位置, 没有实现这个emoji, 只要实现就能显示
8. 计算emoji的码点
function fixedCharCodeAt (str, idx) {
// ex. fixedCharCodeAt ('\uD800\uDC00', 0); // 65536
// ex. fixedCharCodeAt ('\uD800\uDC00', 1); // false
idx = idx || 0;
var code = str.charCodeAt(idx);
var hi, low;
// High surrogate (could change last hex to 0xDB7F to treat high
// private surrogates as single characters)
if (0xD800 <= code && code <= 0xDBFF) {
hi = code;
low = str.charCodeAt(idx+1);
if (isNaN(low)) {
throw 'High surrogate not followed by low surrogate in fixedCharCodeAt()';
}
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
// We return false to allow loops to skip this iteration since should have
// already handled high surrogate above in the previous iteration
return false;
/*hi = str.charCodeAt(idx-1);
low = code;
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;*/
}
return code;
}
0xD800
1101100000000000
0xDBFF
1101101111111111
0x400
10000000000
0xDC00
1101110000000000
0x10000
10000000000000000
网友评论