由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。未经本人同意,请勿转载!
路漫漫其修远兮,吾将上下而求索。
由char和byte的关系引申出去——总结一下java中的字符编码相关知识的更多相关文章
- 字符编码:Unicode和UTF-8之间的关系
Unicode和UTF-8之间的关系 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256 ...
- java 中String编码和byte 解码总结——字节流和字符流
1.InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符 InputStreamReader(InputStream in, Strin ...
- 字符编码:Unicode和UTF-8的关系
今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思 ...
- .NET和JAVA中BYTE的区别以及JAVA中“DES/CBC/PKCS5PADDING” 加密解密在.NET中的实现
场景:java 作为客户端调用已有的一个.net写的server的webservice,输入string,返回字节数组. 问题:返回的值不是自己想要的,跟.net客户端直接调用总是有差距 分析:平台不 ...
- c#与java中byte字节的区别及转换方法
原文:c#与java中byte字节的区别及转换方法 在java中 byte的范围在 [-128,127] 在C#中 byte的范围在 [0,255] 所以 java程序与C#程序 进行数据传输的时 ...
- java中的byte有什么作用?
byte即字节的意思,是java中的基本类型,用心申明字节型的变量. 通常在读取非文本文件时(如图片,声音,可执行文件)需要用字节数组来保存文件的内容,在下载文件时,也是用byte数组作临时的缓冲器接 ...
- 为什么 char 数组比 Java 中的 String 更适合存储密码?
另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题.这是一个真正艰难的核心Java面试问题,并且需要对 String 的扎实知识才能回答这个问题. ...
- 计算机基础--Java中int char byte的关系
计算机基础--Java中int char byte的关系 重要:一个汉字占用2byte,Java中用char(0-65535 Unicode16)型字符来存字(直接打印输出的话是字而非数字),当然要用 ...
- java基础类型中的char和byte的辨析及Unicode编码和UTF-8的区别
在平常工作中使用到char和byte的场景不多,但是如果项目中使用到IO流操作时,则必定会涉及到这两个类型,下面让我们一起来回顾一下这两个类型吧. char和byte的对比 byte byte 字节, ...
- 从源码和doc揭秘——Java中的Char究竟几个字节,Java与Unicode的关系
#编码与字符编码 (懂编码的建议直接跳过) 在计算机世界中,任何事物都是用二进制图片数字表示的,图片可以编码为JPG,PNG格式的字节流,音频,视频有MP3,MP4格式的字节流.这些JPG,MP3等都 ...
随机推荐
- JetBrains Fleet初体验,如何运行一个java项目
序言 各位好啊,我是会编程的蜗牛,JetBrains 日前宣布其打造的下一代 IDE Fleet 正式推出公共预览版,现已开放下载.作为java开发者,对于JetBrains开发的全家桶可以说是印象深 ...
- v-for和router-link的共同使用
1. 错误例子 <div style="color: red" v-for="item in pressionList" :key="item. ...
- 2.签名&初始化&提交
Git设置签名 签名的作用是区分不同操作者的身份,用户的签名信息在每一个版本的提交信息中能够看到, 以此确认本次提交是谁做的,git首次安装必须设置用户签名,否则无法提交代码 这里设置的用户签名和 ...
- vue3+element-plus+登录逻辑token+环境搭建
vue3+element-plus+登录逻辑token环境搭建 安装脚手架工具 1 npm i @vue/cli@4.5.13 -g 验证是否安装成功 1 vue -V # 输出 @vue/cli 4 ...
- 十五、资源控制之Deployment
资源控制器之Deployment Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationControlle ...
- JVM学习笔记——垃圾回收篇
JVM学习笔记--垃圾回收篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的垃圾回收部分 我们会分为以下几部分进行介绍: 判断垃圾回收对象 垃圾回收算法 分代垃圾回收 垃圾回收器 ...
- Spring Boot 中使用 Swagger
前后端分离开发,后端需要编写接⼝说明⽂档,会耗费⽐较多的时间. swagger 是⼀个⽤于⽣成服务器接⼝的规范性⽂档,并且能够对接⼝进⾏测试的⼯具. 作用 ⽣成接⼝说明⽂档 对接⼝进⾏测试 使用步骤 ...
- JVM学习笔记——类加载和字节码技术篇
JVM学习笔记--类加载和字节码技术篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的类加载和字节码技术部分 我们会分为以下几部分进行介绍: 类文件结构 字节码指令 编译期处理 类 ...
- java判断手机号三大运营商归属的工具类
package com.tymk.front.third; import java.util.regex.Pattern; public class OperatorsUtil { /** * 中国电 ...
- win10系统VMWare16 Pro 安装CentOS8
目录 一.本机环境与问题解决 二.下载软件 三.VMWare16 Pro安装 四.CentOS8 安装 一.本机环境与问题解决 装了好几遍,感觉坑都踩了一遍,泪奔~,还好终于跑起来了! 查看电脑是否开 ...