|
转载请注明文章出处:https://itlanyan.com/string-unicode-utf8-converter/
( s! R, G: X, ^! i: b想知道某个字符串的UTF8编码,图方便打算使用在线工具。坑爹的是,号称“UTF8汉字互转”的网页几乎全是字符串和unicode码点互转,并不提供与UTF8编码互转功能。没搞懂unicode码点(code point)和UTF8编码的关系,还大言不惭的说UTF8编码,真让人无语。
# m! v) t9 r$ k& o5 ^) K/ O
j" C. h J9 T2 o! B1 w; E
; T! m6 h& P- k, r( b
! j2 E3 Y& Q! A/ Y8 @5 Z, T& r" Z
J; M% z r- H# g7 Z5 u+ N6 P% j3 i, ?! z# K+ G, d% t
字符、字节和字节序,unicode和UTF8编码,是理解字符编码重要的概念,详情可查看本人之前博文文件和字符编码。本文讨论unicode和UTF8之间的转换,先简要介绍两个概念:unicode是将字符与码点(code point,一个整数)一一对应的编码方案;码点通常用\uXXXX或者U+XXXX的方式表示,XXXX是码点的十六进制;UTF8是unicode的一个具体编码方案,规定字符存储的方式;UTF8编码字节数可变,不存在大小端问题,互联网通信中常采用此种编码方式。
4 Q' e+ w" M* p8 L回顾一下那成片的“汉字UTF8编码互转”网页所做的事情。以“中国”为例,两个汉字码点分别为20013和22269,十六进制表示4E2D 56FD,UTF8编码E4 B8 AD E5 9B BD。随手打开搜索结果中的http://www.ip138.com/utf8/,输入“中国”,点击“转换UTF-8”按钮,下方出现码点的十六进制编码4E2D 56FD(&#x可以理解为十六进制的前缀0x),并非UTF8编码。& ]) R& {) @+ Z0 u8 J7 C1 W
JavaScript的String对象有charCodeAt和codePointAt(兼容性不如charCodeAt)方法。根据这个函数,网页的转换工作可用如下代码实现:
) }* O5 t6 D1 m% I1 q& p, ffunction encode(str) {* H H1 K9 |7 J, R7 C" s+ e
var result = '';
8 q- }( p& |# H* a9 J! B8 J var len = str.length;
x; Z4 M9 g4 I/ l5 ?2 b for (var i = 0; i 调用encode(“中国”)或者其他字符串,将得到每个字符对应码点的十六进制。但这不是字符串的UTF8编码!
, ^& A& Y, M3 e- x( g- k8 o要拿到UTF8编码,需要在码点的基础上多走一步。先回顾unicode码点与UTF8的转换关系:
% K. h) c; U2 i8 f l3 `9 P# L) J) ~unicode码点(十六进制)[/td]UTF-8(二进制) | 0000 0000-0000 007F | 0xxxxxxx | 0000 0080-0000 07FF | 110xxxxx 10xxxxxx | 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 根据这个表,结合charCodeAt函数,可以写出字符串到UTF8编码的函数:/ L. m% Y& J/ f1 \! ?7 B, T' E
// 获取字符串的utf8字节流, h5 G8 d6 r0 ]
function getUTF8Bytes(str) {
3 y ?8 O; y- F% k) [1 i2 t var bytes = [];( g* [ ]. P4 F1 E$ J# r; @
var len = str.length;
2 c& _; B! n4 r8 k# ]; o for (var i = 0; i = 0x10000 && code > 18) | 0xf0); // 第一个字节6 N& \6 b% N9 a- n
bytes.push(((code >> 12) & 0x3f) | 0x80);
5 b e1 v } g6 z+ r bytes.push(((code >> 6) & 0x3f) | 0x80);
1 k) h- v1 m2 H" `9 k2 R/ ^ bytes.push((code & 0x3f) | 0x80);
L. b- n `, U5 ^4 }8 k } else if (code >= 0x800 && code > 12) | 0xe0);/ V& d$ t( ~$ h! B. x1 e
bytes.push(((code >> 6) & 0x3f) | 0x80);$ Z% k. S1 \1 q. I% B
bytes.push((code & 0x3f) | 0x80);
! c( j1 G6 A- y) M" t9 z' ~ } else if (code >= 0x80 && code > 6) | 0xc0);
# R' _2 Z k* `4 K8 P bytes.push((code & 0x3f) | 0x80);' U6 k& P' L% u' J$ c8 N0 d2 P
} else {" J! _3 D; W* v% W1 E
bytes.push(code)
; m. f0 x9 p" |6 R% J' t }
* d4 \% Q; E) p* V }
/ H6 I t+ d f. [. c" M return bytes;
2 \* g2 c4 c; K; e8 X}. H3 M& \/ T6 @5 j: f+ ~# I: N1 c0 t
// 将字节流转换成16进制字符串
1 I! Y% ]4 g2 e! ^# E2 M$ h4 A7 ^$ zfunction hexString(bytes) { p% R# C4 O! ~* _, D) _9 G" y
var arr = bytes.map(function (code) {7 l3 e- k1 k( Z1 M8 d
return (code).toString(16).toUpperCase();
; S' l9 u$ ~, H+ F });" u% s. J3 {6 {
return arr.join(' ');
9 X2 ?1 U# U; }' r' `}
3 M8 r0 h" Y1 d4 w4 m/ ^function utf8(str) {
9 N; G9 H! Y4 w& z9 J$ h+ q: A return hexString(getUTF8Bytes(str));
0 P# _6 ^" F# z% r}; @& T. ]" s$ x3 D0 |) e
调用函数utf8,这才是JavaScript得到字符串的UTF8编码的正确姿势!从UTF8编码转换到字符串,做相反工作即可。
6 Z; x/ ?" v( v, B W8 ]AD:【国外VPS推荐】 Vultr全球16个数据中心,高速SSD硬盘,月付2.5$起,注册充10$送100$打赏赞(1) |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|