中文件编码方式_一文解开java中字符串编码的小秘密
简介:在本文中你将了解到Unicode和UTF-8,UTF-16,UTF-32的关系,同时你还会了解变种UTF-8,并且探讨一下UTF-8和变种UTF-8在java中的应用。
Unicode的发展史
在很久很久以前,西方世界出现了一种叫做计算机的高科技产品。
初代计算机只能做些简单的算数运算,还要使用人工打孔的程序才能运行,不过随着时间的推移,计算机的体积越来越小,计算能力越来越强,打孔已经不存在了,变成了人工编写的计算机语言。
一切都在变化,唯有一件事情没有变化。这件事件就是计算机和编程语言只流传在西方。而西方日常交流使用26个字母加有限的标点符号就够了。
最初的计算机存储可以是非常昂贵的,我们用一个字节也就是8bit来存储所有能够用到的字符,除了最开始的1bit不用以外,总共有128中选择,装26个小写+26个大写字母和其他的一些标点符号之类的完全够用了。
这就是最初的ASCII编码,也叫做美国信息交换标准代码(American Standard Code for Information Interchange)。
后面计算机传到了全球,人们才发现好像之前的ASCII编码不够用了,比如中文中常用的汉字就有4千多个,怎么办呢?
没关系,将ASCII编码本地化,叫做ANSI编码。1个字节不够用就用2个字节嘛,路是人走出来的,编码也是为人来服务的。于是产生了各种如GB2312, BIG5, JIS等各自的编码标准。这些编码虽然与ASCII编码兼容,但是相互之间却并不兼容。
这严重的影响了国际化的进程,这样还怎么去实现同一个地球,同一片家园的梦想?
于是国际组织出手了,制定了UNICODE字符集,为所有语言的所有字符都定义了一个唯一的编码,unicode的字符集是从U+0000到U+10FFFF这么多个编码。
那么unicode和UTF-8,UTF-16,UTF-32有什么关系呢?
unicode字符集最后是要存储到文件或者内存里面的,直接存储的话,空间占用太大。那怎么存呢?使用固定的1个字节,2个字节还是用变长的字节呢?于是我们根据编码方式的不同,分成了UTF-8,UTF-16,UTF-32等多种编码方式。
其中UTF-8是一种变长的编码方案,它使用1-4个字节来存储。UTF-16使用2个或者4个字节来存储,JDK9之后的String的底层编码方式变成了两种:LATIN1和UTF16。
而UTF-32是使用4个字节来存储。这三种编码方式中,只有UTF-8是兼容ASCII的,这也是为什么国际上UTF-8编码方式比较通用的原因(毕竟计算机技术都是西方人搞出来的)。
Unicode详解
知道了Unicode的发展史之后,接下来我们详解讲解一下Unicode到底是怎么编码的。
Unicode标准从1991年发布1.0版本,已经发展到2020年3月最新的13.0版本。
Unicode能够表示的字符串范围是0到10FFFF,表示为U+0000到U+10FFFF。
其中U+D800到U+DFFF的这些字符是预留给UTF-16使用的,所以Unicode的实际表示字符个数是216 − 211 + 220 = 1,112,064个。
我们将Unicode的这些字符集分成17个平面,各个平面的分布图如下:
以Plan 0为例,Basic Multilingual Plane (BMP)基本上包含了大部分常用的字符,下图展示了BMP中所表示的对应字符:
上面我们提到了U+D800到U+DFFF是UTF-16的保留字符。其中高位U+D800–U+DBFF和低位U+DC00–U+DFFF是作为一对16bits来对非BMP的字符进行UTF-16编码。单独的一个16bits是无意义的。
UTF-8
UTF-8是用1到4个字节来表示所有的1,112,064个Unicode字符。所以UTF-8是一种变长的编码方式。
UTF-8目前是Web中最常见的编码方式,我们看下UTF-8怎么对Unicode进行编码:
最开始的1个字节可以表示128个ASCII字符,所以UTF-8是和ASCII兼容的。
接下来的1,920个字符需要两个字节进行编码,涵盖了几乎所有拉丁字母字母表的其余部分,以及希腊语,西里尔字母,科普特语,亚美尼亚语,希伯来语,阿拉伯语,叙利亚语,Thaana和N'Ko字母,以及组合变音符号标记。BMP中的其余部分中的字符需要三个字节,其中几乎包含了所有常用字符,包括大多数中文,日文和韩文字符。Unicode中其他平面中的字符需要四个字节,其中包括不太常见的CJK字符,各种历史脚本,数学符号和表情符号(象形符号)。
下面是一个具体的UTF-8编码的例子:
UTF-16
UTF-16也是一种变长的编码方式,UTF-16使用的是1个到2个16bits来表示相应的字符。
UTF-16主要在Microsoft Windows, Java 和 JavaScript/ECMAScript内部使用。
不过UTF-16在web上的使用率并不高。
接下来,我们看一下UTF-16到底是怎么进行编码的。
首先:U+0000 to U+D7FF 和 U+E000 to U+FFFF,这个范围的字符,直接是用1个16bits来表示的,非常的直观。
接着是:U+010000 to U+10FFFF
这个范围的字符,首先减去0x10000,变成20bits表示的0x00000–0xFFFFF。
然后高10bits位的0x000–0x3FF加上0xD800,变成了0xD800–0xDBFF,使用1个16bits来表示。
低10bits的0x000–0x3FF加上0xDC00,变成了0xDC00–0xDFFF,使用1个16bits来表示。
U' = yyyyyyyyyyxxxxxxxxxx // U - 0x10000
W1 = 110110yyyyyyyyyy // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx // 0xDC00 + xxxxxxxxxx
这也是为什么在Unicode中0xD800–0xDFFF是UTF-16保留字符的原因。
下面是一个UTF-16编码的例子:
UTF-32
UTF-32是固定长度的编码,每一个字符都需要使用1个32bits来表示。
因为是32bits,所以UTF-32可以直接用来表示Unicode字符,缺点就是UTF-32占用的空间太大,所以一般来说很少有系统使用UTF-32.
Null-terminated string 和变种UTF-8
在C语言中,一个string是以null character ('0')NUL结束的。
所以在这种字符中,0x00是不能存储在String中间的。那么如果我们真的想要存储0x00该怎么办呢?
我们可以使用变种UTF-8编码。
在变种UTF-8中,null character (U+0000) 是使用两个字节的:11000000 10000000 来表示的。
所以变种UTF-8可以表示所有的Unicode字符,包括null character U+0000。
通常来说,在java中,InputStreamReader 和 OutputStreamWriter 默认使用的是标准的UTF-8编码,但是在对象序列化和DataInput,DataOutput,JNI和class文件中的字符串常量都是使用的变种UTF-8来表示的。
原文链接
本文为阿里云原创内容,未经允许不得转载。
中文件编码方式_一文解开java中字符串编码的小秘密相关推荐
- python2字符串编码方式_一、基础部分-2.字符串编码
一.字符编码历史 1. ASCII 美国人搞了个ASCII码表,把123abcABC%$#(数字.字母.特殊符号) ,全部用10进制的数字表示.例如数字65,代表着"A" ,ASC ...
- 一文解开java中字符串编码的小秘密
文章目录 简介 Unicode的发展史 Unicode详解 UTF-8 UTF-16 UTF-32 Null-terminated string 和变种UTF-8 简介 在本文中你将了解到Unicod ...
- set集合判断集合中是否有无元素_一文了解 JavaScript 中的 Set(集合)- 对 Set 的扩展...
阅读全文需要 4 分钟.主要介绍对 ES6 中的 Set 集合方法的扩展.阅读本文后,你能创建出对 Set 方法扩展,并且结合下期内容,将其发布到 NPM 中. 往期回顾 一文了解 JavaScrip ...
- java定义接口_一文知道Java中接口的定义
使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成.定义接口的基本格式如下: 方法:接口中的方法只有定义而没有被实现. ...
- java中二进制怎么说_面试:说说Java中的 volatile 关键词?
volatile 这个关键字可能很多朋友都听说过,或许也都用过.在 Java 5 之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 Java 5之后,volatile 关 ...
- python统计字符在文件中出现的次数_一文搞定统计字符串中某字符出现的频次
下面是统计字符串中某字符出现的次数的方法 方法1: 这个方法相当简单,零基础自学编程,代码写成这样能满足需求,但它逐个逐个计数,比较笨拙.rlt = {} for i in content: if i ...
- java读取文件特别慢_如何提高在Java中读取大文件的速度?
我只读了一个大小为167MB且行号为1884000的文件.我使用的方法是BufferedReader,以获得读取它的效果. 我注意到,随着当前行号的增加,读取文件的过程越来越慢(在这种情况下,我花了3 ...
- bms中soh计算方式_干货丨BMS算法中关于健康状态(SOH)的模型设计来自IND4汽车人叶磊Ray的分享...
众所周知动力电池系统经过长期运行性能将不断的衰减,如何有效的评估电池健康度SOH(state of health)不仅是计算SOC.SOP等关键参数的重要依据,同时对评判动力电池系统何时需更换.是否可 ...
- bms中soh计算方式_原创丨BMS算法中关于健康状态(SOH)的模型设计
作为消费者我们使用电池的经验往往是用得越久电池的续航就越少,功率性能就越差,总的来说就是动力电池性能会随着"运行使用"不断"性能衰减".在算法层面一般会将&qu ...
最新文章
- p,v原语解决和尚挑水问题
- Google单季度,营收超过753亿美元
- mysql 以数组的形式插入更新表
- 《系统集成项目管理工程师》必背100个知识点-71合同变更控制系统
- [pytorch、学习] - 4.5 读取和存储
- Codeforces 821C - Okabe and Boxes
- python asyncio 异步编程---协程
- refresh的停车场
- JavaScript 'Pig latin is cool'=='igPay atinlay siay oolcay'
- 我的考研~~~3-4月份总结
- nginx server_name
- 机器学习中的数学系列
- php二维数组引用变量,PHP二维数组的引用赋值容易犯的错误
- python通信工程定额_通信工程2008版定额和2017版定额简单对比
- 自动将视频文件生成字幕的软件autosub的替代工具字幕酱(支持英文、日语和法语、德语、韩语)
- 求过度矩阵+(二次型标准化)正交变换的过度矩阵
- chrome无法打开应用商店添加扩展程序的解决方案
- 0ctf-2017-pwn-char 题解
- 使用h5新增的canvas标签绘制太极图案-代码
- 获取选股宝7x24小时数据