Unicode 的发展,英文好的直接去 unicode.org 上去看吧,不好的可以移步到这里
看dengyunze的总结:《关于UTF8,UTF16,UTF32,UTF16-LE,UTF16-BE 》
。此文讲的清除明白:为了能把世界上的所有字符都表示,理论上需要用 UTF-16,但是由于“大部分”(当然这是欧美那边技术宅男拍脑袋想出来的大部分啦~)的字符只需要 1 个字节就搞定了,用 UTF16 实在太浪费啦,于是他们就用了 UTF8. 对于那些个“少数”(比如中日韩)的字符,就通过一个 UTF8-UTF16 的转换来表示。

UTF8 和 UTF16 都是变长表示的,为啥欧美技术宅会觉得太浪费了咧?因为欧美字符 0x0000 - 0x00FF 就搞定了,UTF8 最小变长是 1 个字节,而 UTF16 变长是 2 个字节,所以……(↓看下图中 code unit size)

注意:上面这个图中,UTF-16 和 UTF-16LE 是一样的,因为…… UTF16 默认就是 UTF-16LE

 

那么,UTF8是如何表示
的咧?↓看下图

 

↓↓ 举例

表示的方法跟上上个图对应,第一个字节中,从左往右第一个 10 前面的 “1” 的个数表示后面还有这么多个的字节在表示这个字符。UTF8 最多可以表示 31 bit 的字符。

 

 

UTF16 编码的过程

v  = 0x64321
v′ = v - 0x10000
= 0x54321
= 0101 0100 0011 0010 0001
vh = v′ >> 10
= 01 0101 0000 // higher 10 bits of v′
vl = v′ & 0x3FF
= 11 0010 0001 // lower 10 bits of v′
w1 = 0xD800 + vh
= 1101 1000 0000 0000
+ 01 0101 0000
= 1101 1001 0101 0000
= 0xD950 // first code unit of UTF-16 encoding
w2 = 0xDC00 + vl
= 1101 1100 0000 0000
+ 11 0010 0001
= 1101 1111 0010 0001
= 0xDF21 // second code unit of UTF-16 encoding

 

附一段 java 版本的 UTF8 与 UTF16 的相互转换,代码来源于 Lucene3.6

/**
* Interprets the given byte array as UTF-8 and converts to UTF-16. The
* {@link CharsRef} will be extended if it doesn't provide enough space to
* hold the worst case of each byte becoming a UTF-16 codepoint.
* <p>
* NOTE: Full characters are read, even if this reads past the length passed
* (and can result in an ArrayOutOfBoundsException if invalid UTF-8 is
* passed). Explicit checks for valid UTF-8 are not performed.
*/
// TODO: broken if chars.offset != 0
public static void UTF8toUTF16(byte[] utf8, int offset, int length,
CharsRef chars) {
int out_offset = chars.offset = 0;
final char[] out = chars.chars = ArrayUtil.grow(chars.chars, length);
final int limit = offset + length;
while (offset < limit) {
int b = utf8[offset++] & 0xff;
if (b < 0xc0) {
assert b < 0x80;
out[out_offset++] = (char) b;
} else if (b < 0xe0) {
out[out_offset++] = (char) (((b & 0x1f) << 6) + (utf8[offset++] & 0x3f));
} else if (b < 0xf0) {
out[out_offset++] = (char) (((b & 0xf) << 12)
+ ((utf8[offset] & 0x3f) << 6) + (utf8[offset + 1] & 0x3f));
offset += 2;
} else {
assert b < 0xf8 : "b=" + b;
int ch = ((b & 0x7) << 18) + ((utf8[offset] & 0x3f) << 12)
+ ((utf8[offset + 1] & 0x3f) << 6)
+ (utf8[offset + 2] & 0x3f);
offset += 3;
if (ch < UNI_MAX_BMP) {
out[out_offset++] = (char) ch;
} else {
int chHalf = ch - 0x0010000;
out[out_offset++] = (char) ((chHalf >> 10) + 0xD800);
out[out_offset++] = (char) ((chHalf & HALF_MASK) + 0xDC00);
}
}
}
chars.length = out_offset - chars.offset;
} /** Encode characters from a char[] source, starting at
* offset for length chars. After encoding, result.offset will always be 0.
*/
public static void UTF16toUTF8(final char[] source, final int offset, final int length, BytesRef result) { int upto = 0;
int i = offset;
final int end = offset + length;
byte[] out = result.bytes;
// Pre-allocate for worst case 4-for-1
final int maxLen = length * 4;
if (out.length < maxLen)
out = result.bytes = new byte[maxLen];
result.offset = 0; while(i < end) { final int code = (int) source[i++]; if (code < 0x80)
out[upto++] = (byte) code;
else if (code < 0x800) {
out[upto++] = (byte) (0xC0 | (code >> 6));
out[upto++] = (byte)(0x80 | (code & 0x3F));
} else if (code < 0xD800 || code > 0xDFFF) {
out[upto++] = (byte)(0xE0 | (code >> 12));
out[upto++] = (byte)(0x80 | ((code >> 6) & 0x3F));
out[upto++] = (byte)(0x80 | (code & 0x3F));
} else {
// surrogate pair
// confirm valid high surrogate
if (code < 0xDC00 && i < end) {
int utf32 = (int) source[i];
// confirm valid low surrogate and write pair
if (utf32 >= 0xDC00 && utf32 <= 0xDFFF) {
utf32 = (code << 10) + utf32 + SURROGATE_OFFSET;
i++;
out[upto++] = (byte)(0xF0 | (utf32 >> 18));
out[upto++] = (byte)(0x80 | ((utf32 >> 12) & 0x3F));
out[upto++] = (byte)(0x80 | ((utf32 >> 6) & 0x3F));
out[upto++] = (byte)(0x80 | (utf32 & 0x3F));
continue;
}
}
// replace unpaired surrogate or out-of-order low surrogate
// with substitution character
out[upto++] = (byte) 0xEF;
out[upto++] = (byte) 0xBF;
out[upto++] = (byte) 0xBD;
}
}
//assert matches(source, offset, length, out, upto);
result.length = upto;
}

UTF8 与 UTF16 编码的更多相关文章

  1. 快来领取一场专门讲解UTF-8与UTF-16编码算法的GitChat活动的免费名额

    微信扫一扫,可打开该GitChat活动页面 字符编码是计算机世界里最基础.最重要.最令人困惑的一个主题之一.不过,在计算机教材中却往往浮光掠影般地草草带过,甚至连一本专门进行深入介绍的专著都找不到(对 ...

  2. Javascript中的string类型使用UTF-16编码

    2019独角兽企业重金招聘Python工程师标准>>> 在JavaScript中,所有的string类型(或者被称为DOMString)都是使用UTF-16编码的. MDN DOMS ...

  3. 字符编码笔记:ASCII、Unicode、UTF-8、UTF-16、UCS、BOM、Endian

    转载:http://witmax.cn/character-encoding-notes.html 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问 ...

  4. Unicode 字符集及UTF-8 UTF-16编码

    很久以前发在他处的一篇博文,今天翻出来重新整理了一下 Unicode 字符集 共分为 17 个平面(plane), 分别对应 U+xx0000 - U+xxFFFF 的 code points, 其中 ...

  5. UTF-8、UTF-16、UTF-32编码的相互转换

    最近在考虑写一个可以跨平台的通用字符串类,首先需要搞定的就是编码转换问题. vs默认保存代码文件,使用的是本地code(中文即GBK,日文即Shift-JIS),也可以使用带BOM的UTF-8.gcc ...

  6. 字符编码终极笔记:ASCII、Unicode、UTF-8、UTF-16、UCS、BOM、Endian

    1.字符编码.内码,顺带介绍汉字编码 字符必须编码后才能被计算机处理.计算机使用的缺省编码方式就是计算机的内码.早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB231 ...

  7. 由iPhone emoji问题牵出UTF-16编码,UTF-8编码查询

    前言 iOS平台,系统输入法emoji表达.表达式不能在很多其他平台上显示,尤其是在Android.Symbian系统.我决定到底要探索1:我指的是一些知识: (注意:该博文已经如果读者已经了解utf ...

  8. 字符编码的种类:ASCII、GB2312、GBK、GB18030、Unicode、UTF-8、UTF-16、Base64

    ASCII码ASCII:https://zh.wikipedia.org/wiki/ASCIIASCII(American Standard Code for Information Intercha ...

  9. 所谓编码--泛谈ASCII、Unicode、UTF8、UTF16、UCS-2等编码格式

    最近在看nodejs的源码,看到stream的实现里面满地都是encoding,不由想起以前看过的一篇文章--在前面的随笔里面有提到过--阮一峰老师的<字符编码笔记:ASCII,Unicode和 ...

随机推荐

  1. Maven管理多模块项目

    首先,我们要明确的多模块项目的含义,它是指一个应用中包含多个module.一般来说,一个应用单独部署成服务,只是打包的时候,maven会把各个module组合在一起.各模块一般单独打成jar放到lib ...

  2. c函数调用过程原理及函数栈帧分析

    转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707       今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...

  3. homework-04 单词方阵

    问题描述 本次作业的题目要求利用给定的一组单词生成一个矩阵,矩阵的每个位置由一个字母填充,单词表中的每一个单词可以匹配矩阵中一段连续的序列,这段序列可以是横向,纵向或者是45度斜角方向,单词可以由左向 ...

  4. Spring入门(6)-使用注解装配

    Spring入门(6)-使用注解装配 本文介绍如何使用注解装配. 0. 目录 使用Autowired 可选的自动装配 使用Qualifier选择 1. 使用Autowired package com. ...

  5. C语言经典算法100例(一)

    C语言中有有许多经典的算法,这些算法都是许多人的智慧结晶,也是编程中常用的算法,这里面包含了众多算法思想,掌握这些算法,对于学习更高级的.更难的算法都会有很大的帮助,会为自己的算法学习打下坚实的基础. ...

  6. java命令行运行jar里的main类

    一般运行包含manifest的jar包,可以使用 java -jar <jar-file-name>.jar 如果jar里没有 manifest,则可以使用 java -cp foo.ja ...

  7. OpenStack API 与 CloudStack API 模块比较

    OpenStack API Block Storage Service API Compute API Compute API extensions Identity Service API and ...

  8. Squid 日志详解

    原文地址: http://www.php-oa.com/2008/01/17/squid-log-access-store.html access.log 日志 在squid中access访问日志最为 ...

  9. 深入了解 Dojo 的服务器推送技术

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  10. 使用Unity制作游戏关卡的教程(三)

    转自:http://gamerboom.com/archives/75593 作者:Matthias Zarzecki 本文是“使用Unity制作<The Fork Of Truth>的关 ...