UTF-8编码规则

本文详细介绍了UTF-8编码方式,包括变长字节编码原理及其与Unicode编码的关系。通过实例演示了如何从UTF-8编码还原出Unicode编码,并提供了一段Java代码验证这一过程。

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
因此UTF-8中可以用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。
实际将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数。
因此那些基本ASCII字符集中的字符(UNICODE兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示。

对于上面的问题,代码中给出的两个字节是
十六进制:C0 B1
二进制:11000000 10110001
对比两个字节编码的表示方式:
110xxxxx 10xxxxxx
提取出对应的UNICODE编码:
00000 110001
可以看出此编码并非“标准”的UTF-8编码,因为其第一个字节的“有效编码”全为0,去除高位0后的编码仅有6位。由前面所述,此字符仅用一个字节的UTF-8编码表示就够了。
JAVA在把字符还原为UTF-8编码时,是按照“标准”的方式处理的,因此我们得到的是仅有1个字节的编码。

大家可以试试运行这段代码:
public class TestUTF8 {
public static void main(String[] args) throws Exception {
byte[][] bytes = {
// 00110001
{(byte)0x31},
// 11000000 10110001
{(byte)0xC0,(byte)0xB1},
// 11100000 10000000 10110001
{(byte)0xE0,(byte)0x80,(byte)0xB1},
// 11110000 10000000 10000000 10110001
{(byte)0xF0,(byte)0x80,(byte)0x80,(byte)0xB1},
// 11111000 10000000 10000000 10000000 10110001
{(byte)0xF8,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0xB1},
// 11111100 10000000 10000000 10000000 10000000 10110001
{(byte)0xFC,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0xB1},
};
for (int i = 0; i < 6; i++) {
String str = new String(bytes[i], "UTF-8");
System.out.println("原数组长度:" + bytes[i].length +
"/t转换为字符串:" + str +
"/t转回后数组长度:" + str.getBytes("UTF-8").length);
}
}
}
运行结果为:
原数组长度:1 转换为字符串:1 转回后数组长度:1
原数组长度:2 转换为字符串:1 转回后数组长度:1
原数组长度:3 转换为字符串:1 转回后数组长度:1
原数组长度:4 转换为字符串:1 转回后数组长度:1
原数组长度:5 转换为字符串:1 转回后数组长度:1
原数组长度:6 转换为字符串:1 转回后数组长度:1


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/sandyen/archive/2006/08/23/1108168.aspx

### UTF-8 编码规则详解 UTF-8 是一种用于 Unicode 的可变长度字符编码,能够通过 1 到 4 个字节来表示每一个 Unicode 符号。这种设计使得 UTF-8 能够高效地处理不同范围内的字符集[^4]。 #### 字符编码规则 UTF-8 使用以下规则定义如何将 Unicode 码点映射为字节序列: 1. **对于 ASCII 字符 (U+0000 至 U+007F)** 这些字符仅需一个字节即可表示,其二进制形式与标准 ASCII 完全一致。具体来说,第一个字节的最高位始终为 `0`,其余 7 位用来存储字符的实际值。例如: ```plaintext 'A' -> 0x41 (二进制: 01000001) ``` 2. **对于扩展拉丁字母和其他常见字符 (U+0080 至 U+07FF)** 需要两个字节来表示这些字符。第一个字节以 `110xxxxx` 开头,第二个字节以 `10xxxxxx` 开头。其中 `x` 表示实际数据位。例如: ```plaintext '€' (欧元符号, Unicode 码点 U+20AC) -> 11100010 10000010 10101100 (十六进制: E2 82 AC) ``` 3. **对于其他常用字符 (U+0800 至 U+FFFF)** 需要三个字节来表示这些字符。第一个字节以 `1110xxxx` 开始,第二和第三个字节均以 `10xxxxxx` 开始。例如: ```plaintext '漢' (汉字 "汉", Unicode 码点 U+6C49) -> 11100110 10110001 10010010 (十六进制: E6 B1 92) ``` 4. **对于罕见字符或特殊用途字符 (U+10000 至 U+10FFFF)** 需要四个字节来表示这些字符。第一个字节以 `11110xxx` 开始,后续三个字节均以 `10xxxxxx` 开始。例如: ```plaintext '😀' (笑脸表情, Unicode 码点 U+1F600) -> 11110000 10011111 10011000 10000000 (十六进制: F0 9F 98 80) ``` #### 设计特点 - **向后兼容性**: 对于 ASCII 字符集合,UTF-8 和传统的单字节编码完全相同,这使其易于集成到现有系统中。 - **自同步能力**: 即使部分字节丢失或者损坏,也可以重新定位下一个有效字符的位置。 - **紧凑性**: 常见字符通常只需要较少的字节数量进行表达,从而节省空间并提高传输效率。 以下是基于 Python 实现的一个简单例子展示如何查看字符串对应的 UTF-8 编码: ```python text = "你好,世界! 😊" utf8_encoded = text.encode('utf-8') print(utf8_encoded.hex()) # 输出十六进制格式的 UTF-8 编码结果 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值