java字符编码浅析
关于这篇文章其实是从一个问题开始的:java中char类型能存储汉字吗?
UTF-8编码
UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2.对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
Unicode符号范围(十六进制) | 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 |
跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
下面,还是以汉字”严”为例,演示如何实现UTF-8编码。
已知”严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此”严”的UTF-8编码需要三个字节,即格式是”1110xxxx 10xxxxxx 10xxxxxx”。然后,从”严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,”严”的UTF-8编码是”11100100 10111000 10100101”,转换成十六进制就是E4B8A5。
UTF-16编码
UTF-16是Unicode的其中一个使用方式。 UTF是 Unicode TransferFormat,即把Unicode转做某种格式的意思。UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。UTF-16的大端和小端储存形式都在用。为了弄清楚UTF-16文件的大小端,在UTF-16文件的开首,都会放置一个U+FEFF字符作为Byte Order Mark(UTF-16LE以FF FE代表,UTF-16BE以FE FF代表),以显示这个文字档案是以UTF-16编码,其中U+FEFF字符在UNICODE中代表的意义是ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。
实例讲解
例1
1 | String s = "I'm 李博玉"; |
输出的结果是什么呢?
FE FF 0 49 0 27 0 6D 0 20 67 4E 53 5A 73 89
16
49 27 6D 20 E6 9D 8E E5 8D 9A E7 8E 89
13
1.UTF-16的编码为什么是16?
对于大部分字符来讲,UTF-16都使用两个字节来存储。但是UTF-16是支持大小端的,所以需要在字符的开头使用两个字节的额外空间指定好它的字节序,FE FF 表示使用大端存储。
7 x 2 + 2 = 16
2.UTF-8的编码为什么是13?
UTF-8是完全兼容ASCII编码的,所以英文是占一个字节,中文大部分占3个字节,不常用的占4个字节
4 + 3 x 3 = 13
例2
String s1 = “李”;
String s2 = ““
System.out.println(s1.length());
System.out.println(s2.length());
输出的结果是什么呢?
1
2
看到这个结果是不是崩溃了,到底怎么回事?
1.首先要明白.length指的是什么,String内部是以char数组的形式存储的,.length是指char数组的长度,char是以UTF-16编码的,李是常用字,UTF-16编码后占两个字节,一个char就能够存储,所以是长度是1,而UTF-16编码后占四个字节,两个char来存储,所以长度是2
原文:大专栏 java字符编码浅析
原文地址:https://www.cnblogs.com/petewell/p/11597582.html
- 关于查看文件的几个小命令(r3笔记第6天)
- 关于纠结的recycle pool的设置(r3笔记第5天)
- 融会贯通学习trigger(r2笔记第4天)
- 完整的R语言预测建模实例-从数据清理到建模预测
- 利用回归模型预测数值型数据(代码)
- 关于ORA-00020问题的反思(r2笔记第3天)
- 查看空间使用情况的脚本(r2笔记第2天)
- 使用dbms_parallel_execute来完成DML的并行(r3笔记第1天)
- 有趣的linux命令总结(78天)
- 生产环境sql语句调优实战第七篇(r2笔记99天)
- 一个普通数据库用户所能查到的"意料之外"的信息(r2笔记98天)
- 查看并行进程的一些简单信息(r3笔记第17天)
- 多行数据的批处理之bulk collect(r3笔记第16天)
- pl/sql中错误的异常处理 (r3笔记第15天)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释