文档章节

UTF-8是如何编码的?

topwqp
 topwqp
发布于 2016/02/22 18:13
字数 1035
阅读 75
收藏 10

众所周知计算机上存储的是二进制0和1,string字符串是如何转变为二进制0和1的呢?

每一个字符都会转换为对应的16进制,16进制也是一堆01代码,就相当于存储在计算机上的01代码。


不同的字符集通过不同的编码方式存储不同数目的字节数。下面以UTF-8是如何编码存储字符为二进制的为例子进行说明:

String a = “A”

a.getBytes().length is 1

byte array is [65]


String a = "ë"

a.getBytes().length is 2

byte array is [-61, -85]

如上所示: A字符占用一个字节 ë字符占用两个字节。

etBytes()假设默认编码方式为UTF-8。

一些字符是一个字节,一些字符是两个字节,或者更多的字节,那么如何进行解码呢?

UTF-8如何进行编码?Wikipedia中给出了相关的规则:

if the first byte starts with 0 then it is a single byte char

if the first byte starts with 110 then it is 2 bytes

if the first byte starts with 1110 then it is 3 bytes

if the first byte starts with 11110 then it is 4 bytes

if the first byte starts with 111110 then it is 5 byte

if the first byte starts with 1111110 then it is 6 byte

翻译: 如果第一个字节以0开始,代表是一个单字节字符。 如果第一个字节以110开始,代表是双字节字符。 如果第一个字节以1110开始,代表是三字节字符。 如果第一个字节以11110开始,代表是四字节字符。 如果第一个字节以111110开始,代表是五字节字符。 如果第一个字节以1111110开始,代表是六字节字符。

所以我们解码就是反推即可: if the first byte starts with 0 then it is a single byte char so it decodes only that byte

if the first byte starts with 110 then it is 2 byte so it decodes 2 consecutive bytes

if the first byte starts with 1110 then it is 3 byte so it decodes 3 consecutive bytes

if the first byte starts with 11110 then it is 4 byte so it decodes 4 consecutive bytes

if the first byte starts with 111110 then it is 5 byte so it decodes 5 consecutive bytes

if the first byte starts with 1111110 then it is 6 byte so it decodes 6 consecutive bytes

下面用表格的方式列出Unicode和16进制以及占用字节之间的关系:

输入图片说明

实例实战

ë

110 xxxxx 10 xxxxxx

110 00011 10 101011

  00011       101011  → binary equivalent of hex pointing to ë

ɟ 110 xxxxx 10 xxxxxx

110 01001 10 011111

  01001     011111   → binary equivalent of hex pointing to ɟ

11100000 10101101 10011111如何解码? 1110代表是三个字节为一个字符: 1110xxxx 10xxxxxx 10xxxxxx

11100000 10101101 10011111

so 0000 101101 011111 is the binary to be decoded.

所以为 0000 101101 011111 每四位为: 0000 1011 0101 1111 为:B5F

The binary is B5F in hexadecimal (If you don't know to convert use this binary to hex converter website ) Now from map B5F means ୟ .


练习:对01000010 01000001 11000011 10110000 11100010 10001011 10110011进行解码

1、第一个字符 01000010 为一个字符: 0100 0010为:42 参考这里 对应字符B

2、第二个字符

01000001 为一个字符: 0100 0001为:41 参考表格 对应字符A

3、第三个字符 11000011 10110000 为一个字符: 0000 11 110000 就是F0, 参考表格 映射为字符:ð

4、第四个字符: 11100010 10001011 10110011 为一个字符: 00010 001011 110011 就是 22F3 参考表格映射为字符:⋳

结论就是:01000010 01000001 11000011 10110000 11100010 10001011 10110011 采用UTF-8编码为BAð⋳

String 的 getBytes("UTF-8")做了什么操作呢?

String s = "ABCDEF⋳";

ABCDEF⋳通过getBytes("UTF-8")被编码为UTF-8格式,它是如何存储的呢? A - 01000001

B - 01000010

C - 01000011

D - 01000100

E - 01000101

F - 01000110

⋳ - 11100010 10001011 10110011

注意:以上是以字节的形式存储在内存中

所以getBytes("UTF-8")是获取每一个字节返回。

在内存中是如何存储的呢?

01000001 代表正数 65 但是11100010 代表负数 -31

所以存储在内存中为: 01000001 - 65

01000010 - 66

01000011 - 67

01000100 - 68

01000101 - 69

01000110 - 70

11100010 - -31

10001011 - -117

10110011 - -77

代码为证:

	         String s = "ABCDEF⋳";
        	 byte[]  bs = s.getBytes("UTF-8");
        	 for(byte  b : bs)
        	 System.out.print(b+",");

输出:

65,66,67,68,69,70,-30,-117,-77

Reference1 Reference2

© 著作权归作者所有

topwqp
粉丝 0
博文 22
码字总数 11562
作品 0
西城
私信 提问
Java 正确的做字符串编码转换

字符串的内部表示? 字符串在java中统一用unicode表示( 即utf-16 LE) , 对于 String s = "你好哦!"; 如果源码文件是GBK编码, 操作系统(windows)默认的环境编码为GBK,那么编译时, JVM将 按...

月下狼
2013/11/19
14.2K
0
UTF-8编码中BOM的检测与删除

所谓BOM,全称是Byte Order Mark,它是一个Unicode字符,通常出现在文本的开头,用来标识字节序(Big/Little Endian),除此以外还可以标识编码(UTF-8/16/32),如果出现在文本中间,则解释...

大数据之路
2012/10/12
680
0
UTF-8编码中BOM的检测与删除

所谓BOM,全称是Byte Order Mark,它是一个Unicode字符,通常出现在文本的开头,用来标识字节序(Big/Little Endian),除此以外还可以标识编码(UTF-8/16/32),如果出现在文本中间,则解释...

workingTiams
2012/11/28
420
1
使用JFinal框架,FreeMarker生成html时以GB2312编码写入文件,如何改为UTF-8

使用JFinal框架,FreeMarker生成html时以GB2312编码写入文件,如何改为UTF-8? 使用的Myeclipse2016 c1 1 ,各种设置编码、项目各种编码、HTML等编码都设置了UTF-8 ,但是发布到tomcat后,h...

红书
2016/04/14
398
2
字符编码问题:Unicode 和 UTF-8

Unicode Unicode 是一种编码,它将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码。这样乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码...

cooffeelis
2017/11/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

前端技术之:Prisma Demo服务部署过程记录

安装前提条件: 1、已经安装了docker运行环境 2、以下命令执行记录发生在MackBook环境 3、已经安装了PostgreSQL(我使用的是11版本) 4、Node开发运行环境可以正常工作 首先需要通过Node包管...

popgis
19分钟前
4
0
数组和链表

数组 链表 技巧一:掌握链表,想轻松写出正确的链表代码,需要理解指针获引用的含义: 对指针的理解,记住下面的这句话就可以了: 将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指...

code-ortaerc
34分钟前
4
0
栈-链式(c/c++实现)

上次说“栈是在线性表演变而来的,线性表很自由,想往哪里插数据就往哪里插数据,想删哪数据就删哪数据...。但给线性表一些限制呢,就没那么自由了,把线性表的三边封起来就变成了栈,栈只能...

白客C
52分钟前
40
0
Mybatis Plus service

/** * @author beth * @data 2019-10-20 23:34 */@RunWith(SpringRunner.class)@SpringBootTestpublic class ServiceTest { @Autowired private IUserInfoService iUserInfoS......

一个yuanbeth
今天
5
0
php7-internal 7 zval的操作

## 7.7 zval的操作 扩展中经常会用到各种类型的zval,PHP提供了很多宏用于不同类型zval的操作,尽管我们也可以自己操作zval,但这并不是一个好习惯,因为zval有很多其它用途的标识,如果自己...

冻结not
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部