由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中有关字符编码的一些内容,希望能对你有所帮助。

四、 参考资料:

  1. 【你懂乱码吗?锟斤拷烫烫烫(详解ASCII、Unicode、UTF-32、UTF-8编码)】 https://www.bilibili.com/video/BV1xP4y1J7CS/?share_source=copy_web&vd_source=f5db843fce15b7c3e2990f4f7a6e8921
  2. 《java核心技术卷Ⅰ》

鄙人只是一名在读的软件工程专业的本科生,正在复习找工作,故而将复习时遇到的一些有意思的东西总结出来,既是加深理解,也是便于日后复习。

鄙人才疏学浅,若文中有谬误之处,还望诸位不吝斧正,以免误人子弟。若有同道中人想一同讨论学习,也可以联系我=>2938189276@qq.com。未经本人同意,请勿转载!

路漫漫其修远兮,吾将上下而求索。

由char和byte的关系引申出去——总结一下java中的字符编码相关知识的更多相关文章

  1. 字符编码:Unicode和UTF-8之间的关系

    Unicode和UTF-8之间的关系 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256 ...

  2. java 中String编码和byte 解码总结——字节流和字符流

    1.InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符 InputStreamReader(InputStream in, Strin ...

  3. 字符编码:Unicode和UTF-8的关系

    今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思 ...

  4. .NET和JAVA中BYTE的区别以及JAVA中“DES/CBC/PKCS5PADDING” 加密解密在.NET中的实现

    场景:java 作为客户端调用已有的一个.net写的server的webservice,输入string,返回字节数组. 问题:返回的值不是自己想要的,跟.net客户端直接调用总是有差距 分析:平台不 ...

  5. c#与java中byte字节的区别及转换方法

    原文:c#与java中byte字节的区别及转换方法 在java中  byte的范围在 [-128,127] 在C#中  byte的范围在 [0,255] 所以 java程序与C#程序 进行数据传输的时 ...

  6. java中的byte有什么作用?

    byte即字节的意思,是java中的基本类型,用心申明字节型的变量. 通常在读取非文本文件时(如图片,声音,可执行文件)需要用字节数组来保存文件的内容,在下载文件时,也是用byte数组作临时的缓冲器接 ...

  7. 为什么 char 数组比 Java 中的 String 更适合存储密码?

    另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题.这是一个真正艰难的核心Java面试问题,并且需要对 String 的扎实知识才能回答这个问题. ...

  8. 计算机基础--Java中int char byte的关系

    计算机基础--Java中int char byte的关系 重要:一个汉字占用2byte,Java中用char(0-65535 Unicode16)型字符来存字(直接打印输出的话是字而非数字),当然要用 ...

  9. java基础类型中的char和byte的辨析及Unicode编码和UTF-8的区别

    在平常工作中使用到char和byte的场景不多,但是如果项目中使用到IO流操作时,则必定会涉及到这两个类型,下面让我们一起来回顾一下这两个类型吧. char和byte的对比 byte byte 字节, ...

  10. 从源码和doc揭秘——Java中的Char究竟几个字节,Java与Unicode的关系

    #编码与字符编码 (懂编码的建议直接跳过) 在计算机世界中,任何事物都是用二进制图片数字表示的,图片可以编码为JPG,PNG格式的字节流,音频,视频有MP3,MP4格式的字节流.这些JPG,MP3等都 ...

随机推荐

  1. CRT & EXCRT 学习笔记

    这玩意解决的是把同余方程组合并的问题. CRT的核心思想和拉格朗日插值差不多,就是构造一组\(R_i\)使得$\forall i,j(i \neq j) $ \[R_im_i = 1, R_im_j ...

  2. Hive之权限控制

    Hive之权限 一.库级的权限 -- 授予所有权限给某个用户 grant all on msta to user {userName}; -- 授权admin privilege权限 grant AD ...

  3. 【linux】 第1回 linux运维基础

    目录 1. 运维的本质 2. 电脑与服务器 2.1 电脑的种类 2.2 服务器种类 2.3 服务器品牌 2.4 服务器尺寸 2.5 服务器内部组成 3. 磁盘阵列 4. 系统简介 5. 虚拟化 6. ...

  4. 测试杂谈——一条SQL引发的思考(二)

    在前段时间,曾写过一篇关于SQL问题的文章,测试杂谈--一条SQL引发的思考(一). 今天这篇,算是个问题记录吧,问题并不复杂,但对于测试同学而言,确实是个需要关注的点. 问题分析 最近在日常工作中, ...

  5. 基于YOLO和PSPNet的目标检测与语义分割系统(python)

    基于YOLO和PSPNet的目标检测与语义分割系统 源代码地址 概述 这是我的本科毕业设计 它的主要功能是通过YOLOv5进行目标检测,并使用PSPNet进行语义分割. 本项目YOLOv5部分代码基于 ...

  6. Oracle数据库PLSQL编程和存储过程

    一.PLSQL编程 1.1.使用PLSQL实现 Hello world! 1 -- Created on 2022/8/22 by ADMINISTRATOR 2 declare 3 -- 这是申明变 ...

  7. CSS line-break属性与中文标点换行

    关于标点符号把文字带着换行的问题解决方案 出现的问题 最近在弄一个介绍页面的时候遇到一个很巧的问题,在文本换行的时候刚好能够放下文字,但是标点符号把这个文字带着换行了 如下图所示: 如果的在上一行显示 ...

  8. ClickHouse(10)ClickHouse合并树MergeTree家族表引擎之ReplacingMergeTree详细解析

    目录 建表语法 数据处理策略 资料分享 参考文章 MergeTree拥有主键,但是它的主键却没有唯一键的约束.这意味着即便多行数据的主键相同,它们还是能够被正常写入.在某些使用场合,用户并不希望数据表 ...

  9. 我的Vue之旅 10 Gin重写后端、实现页面详情页 Mysql + Golang + Gin

    第三期 · 使用 Vue 3.1 + Axios + Golang + Mysql + Gin 实现页面详情页 使用 Gin 框架重写后端 Gin Web Framework (gin-gonic.c ...

  10. elasticsearch聚合之bucket terms聚合

    目录 1. 背景 2. 前置条件 2.1 创建索引 2.2 准备数据 3. 各种聚合 3.1 统计人数最多的2个省 3.1.1 dsl 3.1.2 运行结果 3.2 统计人数最少的2个省 3.2.1 ...