char在java中是用来干嘛的(由char和byte的关系引申出去——总结一下java中的字符编码相关知识)
由char和byte的关系引申出去——总结一下java中的字符编码相关知识
一 、字符编码
手持两把锟斤拷 ,口中直呼烫烫烫
在文章伊始 ,先来复习一下计算机中关于编码的一些基础知识 ,着重理清以下几个基本概念 。
1. 码点(code point) 计算机只能以二进制的形式存储文字 ,故而计算机中每一个字母 ,文字 ,符号 ,emoji都对应着一个二进制数 ,而这个二进制数就是码点 。
2. 字符集 光有码点还不够 ,我们还得知道有哪些码点 ,这些码点又能表示哪些字符 ,于是便又到了喜闻乐见的制定标准环节 。标准所支持的所有字符及其对应码点的集合被称为字符集 。例如学过C语言的同学都知道的ASCII字符集 ,它共包含了128个字符,包括数字 ,26个字母的大小写及一些符号 ,对应的码点就是0-127 。再有就是后面要提到的Unicode字符集 。
3. 编码 以ASCII字符集为例,它的码点为0-127 ,最大不超过7bit ,而计算机中一般是以8bit的字节(byte)为单位 。出于种种考量 ,实际存储在计算机中的码点的二进制都会在头部添0 ,以8bit存储 。例如A对应码点65 ,二进制为100 0001 ,实际在计算机中存储为0100 0001 。这种在计算机中实际存储的内容到字符的映射就是编码 。
我们熟悉的编码方式有ASCII ,UTF-8 ,UTF-16 ,欧洲的ISO ,中国大陆的GBK等等 。计算机中存储的同一段二进制 ,用不同的编码方式 ,会得到完全不同的内容 。
4. Unicode字符集 ASCII一共只包含了128个字符,显然不够用 ,于是便有了Unicode字符集。Unicode字符集中收录了世界上绝大多数文字 ,符号等,反正就是非常多 。
行文至此 ,笔者想到自己当初学习时的一个疑惑 ,即字符集已经规定好了字符到码点的映射 ,为啥还有各种不同的编码方式 。如果读者仔细理解了上文不难发现 ,在计算机中以何种方式存储码点是需要编码来确定。最简单的方法就是直接将码点转成二进制存储 ,比如对ASCII字符集的ASCII编码 ,对Unicode的UTF-32编码 。
由于Unicode字符集数量极其旁大 ,单个字符最大已超过了3个字节(具体多大我也不清楚 ,目前用4个字节还足够表示) ,同时为了区分前后两个字符在哪里断开 ,utf-32编码简单粗暴得将每个字符以32位4字节的形式存储在计算机中 。这样很好理解 ,但带来了严重的空间浪费 ,对于常用的字母得要存一堆0,简直就是0溢事件 。
5. UTF-8编码 我们常见的utf-8便是为了解决上述问题而诞生的 ,他是针对于Unicode的可变长度编码方式 ,可以把不同字符以1,2 ,3 ,4字节大小存储到计算机中 ,同时utf-8兼容ascii ,具体规则参考下图 ,也推荐大家看一下图片下方链接的视频 ,讲的很好:
图片来源:【你懂乱码吗?锟斤拷烫烫烫(详解ASCII 、Unicode 、UTF-32 、UTF-8编码)】 https://www.bilibili.com/video/BV1xP4y1J7CS/?share_source=copy_web&vd_source=f5db843fce15b7c3e2990f4f7a6e8921
二 、Java中的字符编码
1. 编码方式: 有了以上知识的铺垫 ,其实接下来的问题就很好解决了 。
首先 ,java中采用的是基于Unicode字符集的UTF-16编码方式 。utf-16可以将不同字符以2或4字节大小存储在计算机中 ,可能有同学已经发现规律了 ,utf-8是以8bit为最小单位 ,而utf-16是以16 bit为最小单位 ,而这个最小单位实际上就是所谓的代码单元(code unit) 。
2. char类型: 基本类型char类型就是一个16bit的代码单元 。我们日常里常用的字符,如字母 ,汉字等只需要一个char ,而对于一些类似于emoji这样的码点值很大的字符,需要两个char 。
java中char类型的字面量用A单引号括起来 ,表示一个字符常量 。对于一些特殊字符 ,如回车 ,换行 ,我们要用到转义字符来表示 ,如下图:
图片来源:《java核心技术卷Ⅰ》
3. 应用: 行文至此 ,笔者又想起之前曾经看到过的一个相关的案例 。
简言之就是需要对数据库中取出的用户名做一个截断 ,比如某些情况下只需要呈现用户名的前三个字 。而这个系统允许用户上传的用户名中包含emoji表情 。
在这种情况下就要注意了 ,一个emoji字符由两个char组成 ,如果简单得用String.subString()或者String.length是有问题的 ,因为这些方法都是以char为单位 ,可能会造成把一个emoji字符只截了一个char出来 ,从而导致问题。在这里就需要用String的codePoint相关的方法去截取,以码点为单位 ,因为一个码点一定代表一个字符 ,而一个char则未必 。
详情见该视频:【Emoji 表情导致线上故障2个小时 。老板直接损失10万。到底是什么问题?| 故障复盘 | 实战经验分享】 https://www.bilibili.com/video/BV1MG41177pT/?share_source=copy_web
三 、 总结:
如果您坚持看到了这里,那么我想一定已经对于我标题提出的问题的答案了然于胸了 。
char和byte的关系 ,现在看来这俩也没啥关系嘛 ,只能说我这个引申不是很合适 。本文着重介绍了计算机字符编码的相关知识 ,同时也总结了java中有关字符编码的一些内容 ,希望能对你有所帮助 。
四 、 参考资料:
【你懂乱码吗?锟斤拷烫烫烫(详解ASCII 、Unicode 、UTF-32 、UTF-8编码)】 https://www.bilibili.com/video/BV1xP4y1J7CS/?share_source=copy_web&vd_source=f5db843fce15b7c3e2990f4f7a6e8921 《java核心技术卷Ⅰ》鄙人只是一名在读的软件工程专业的本科生 ,正在复习找工作 ,故而将复习时遇到的一些有意思的东西总结出来 ,既是加深理解 ,也是便于日后复习 。
鄙人才疏学浅 ,若文中有谬误之处 ,还望诸位不吝斧正 ,以免误人子弟 。若有同道中人想一同讨论学习 ,也可以联系我=>2938189276@qq.com 。未经本人同意,请勿转载!
路漫漫其修远兮 ,吾将上下而求索 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!