深入浅出:java开发中,字符集编码详解

深入浅出:java开发中,字符集编码详解

/p>

为什么想起要详细学习记录一下这个课题呢因为我突然发现,绝大多数程序员(特别是培训机构出身的兄弟)
开发中一碰到和字符、字节、编码一类的问题完全是一问三不知。面试的时候刷下一大把。

还是那句话,不要去奢望什么高端、前卫、高大上的技术。以为会一点皮毛说两句专业名词自己就是高级程序员了。 静下心来,把基础的学懂学透,最后你会发现一切都豁然开朗了。

目录

  • 深入浅出:java开发中,字符集编码详解
    • 1.什么是字符集编码:
    • 2.常用字符集和字符编码:
      • 2.1. ASCII
      • 2.2. Unicode
        • 2.2.1 UTF-8
        • 2.2.1 UTF-16(了解)
        • 2.2.1 UTF-32(了解)
      • 2.3. GBK系列
      • 2.4.ISO系列
    • 3.GBK和UTF-8怎么选:
      • 3.1 面试题,一个汉字占几个字节/li>
    • 4.java开发中,怎么知道系统默认的编码格式/li>
    • 5.java开发中,怎么判断乱码字符串的编码/li>
    • 6.java开发中,怎么改变字符串的编码/li>

1.什么是字符集编码:

我相信,这个问题很多人在工作中都不知道也不敢问。说真的我一开始也不知道,我不好意思问同事,因为我觉得这种问题一旦问出口,大家都投来鄙夷的眼神。但最后我才发现,我身边的程序员其实都他妈答不上这个问题。

首先,请问,计算机认识我们的“ABC”、“张三” 这些东西嘛不认识。计算机只认识0和1。好。那我们怎么通过0和1去表示“ABC”和“张三”呢明的同学知道了,怎么表示呢,**就用一种规则去规定不久好了嘛! **
比如:“A”就是0011;“张”就是1100。 这个过程我们称之为:编码
反之:另一个计算机得到了0011和1100。通过一套规则将它们翻译过来得到“A”和“张”。这个过程我们称之为:解码 。 有意思的是,在解码的时候使用的规则和编码时不是同一套规则,就会出现我们开发时有时会看到的乱码。“бАзЪСЯ”、””

什么是字符集编码首先我们要知道两个概念。

1. 字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。(就是我们键盘能打出来的任何东西,包括空格、换行这类的动作)

2. 字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码。

好,看不懂。不要急,往下看。

/p>

2.常用字符集和字符编码:

2.1. ASCII

ASCII(American Standard Code for Information Interchange,美国信息互换标准代码,ASCⅡ)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。
 ASCII第一次以规范标准的型态发表是在1967年,最后一次更新则是在1986年,至今为止共定义了128个字符,其中33个字符无法显示(这是以现今操作系统为依归,但在DOS模式下可显示出一些诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符,控制字符的用途主要是用来操控已经处理过的文字,在33个字符之外的是95个可显示的字符,包含用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。

ASCII字符集:主要包括控制字符(回车键、退格、换行键等);可显示字符(英文大小写字符、阿拉伯数字和西文符号)。

ASCII编码:将ASCII字符集转换为计算机可以接受的数字系统的数的规则。使用8位(bits)表示一个字符(如:0100 0001表示“A”),共256字符。ASCII字符集映射到数字编码规则如下图所示:

深入浅出:java开发中,字符集编码详解
ASCII编码可支持的字符太少,对于一些国家的外来字符(汉字)不能有效的编码解码。所以出现了其他的编码方式。

2.2. Unicode

Unicode是美国人在吃了ASCII的亏之后,新定义的一种规则,容纳了全世界所有国家使用语言的字符。
Unicode相比ASCII而言,整个逻辑发生了翻天覆地的变化。
我们知道,ASCII是通过一套规则(字典),将所有字符转化为二进制存储。
而Unicode相比起来就聪明多了,因为Unicode要存储的字符远远多于ASCII。一个字符一个字符的定义转换规则太过于傻逼了。怎么做的呢nicode为每个字符规定一个用来表示该字符的数字

以下文字摘自:https://blog.csdn.net/hezh1994/article/details/78899683.
之前提到,Unicode 没有规定字符对应的二进制码如何存储。以汉字“汉”为例,它的 Unicode 码点是 0x6c49,对应的二进制数是 110110001001001,二进制数有 15 位,这也就说明了它至少需要 2 个字节来表示。可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。
这就导致了一些问题,计算机怎么知道你这个 2 个字节表示的是一个字符,而不是分别表示两个字符呢里我们可能会想到,那就取个最大的,假如 Unicode 中最大的字符用 4 字节就可以表示了,那么我们就将所有的字符都用 4 个字节来表示,不够的就往前面补 0。这样确实可以解决编码问题,但是却造成了空间的极大浪费,如果是一个英文文档,那文件大小就大出了 3 倍,这显然是无法接受的。
于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。

2.2.1 UTF-8

奇了怪了,为什么我要把UTF-8放在Unicode目录下呢br> 可以这样理解:Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。

前面我们说到,Unicode没有提供编码方式,它只是把每一个字符转换成一个数字,用数字的二进制码来代表这个字符。
这样造成的问题就是一个《不可知问题》。比如一个字符对应为2个字节的数字,而另一个字符对应4个字节的数字。好! 我在解码的时候,怎么去知道我该取2个字节还是4个字节来解码呢前美国人他们就采用的是一杆子打死的方式:

  1. 我先找出占用字节最多的字符,比如是5个字节。
  2. 好,我现在知道了,这个世界上所有字符,最大就占5个字节。
  3. 那我就让所有的字符都占5个字节,不满5个字节的我补0。
  4. 这样我取的时候我就按5个字节的长度取。

好,这样一来。原本1mb大小的信息。翻了好几倍! 你来评评理,这样不是傻逼了吗。

UTF-8,相信程序员都不陌生。
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码(定长码),也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。(一句话:同时支持ASCII编码)因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。

UTF-8使用1至4个字节为每个字符编码。
编码规则如下:

  1. 对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 – 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。
  2. 对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N – 1 个字节的前两位都设位 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。
    深入浅出:java开发中,字符集编码详解

2.2.1 UTF-16(了解)

16/8 = 2字节;
尽管有Unicode字符非常多,但是实际上大多数人不会用到超过前65535个以外的字符。
UTF-16将0–65535范围内的字符编码成2个字节,如果真的需要表达那些很少使用的”星芒层(astral plane)”内超过这65535范围的Unicode字符,则需要使用一些诡异的技巧来实现。UTF-16编码最明显的优点是它在空间效率上比UTF-32高两倍,因为每个字符只需要2个字节来存储(除去65535范围以外的),而不是UTF-32中的4个字节。并且,如果我们假设某个字符串不包含任何星芒层中的字符,那么我们依然可以在常数时间内找到其中的第N个字符,直到它不成立为止这总是一个不错的推断。

其编码方式我们这里不深究了。

2.2.1 UTF-32(了解)

32/8 = 4字节;
UTF-32又称UCS-4是一种将Unicode字符编码的协定,对每个字符都使用4字节。就空间而言,是非常没有效率的。
这种方法有其优点,最重要的一点就是可以在常数时间内定位字符串里的第N个字符,因为第N个字符从第4×Nth个字节开始。虽然每一个码位使用固定长定的字节看似方便,它并不如其它Unicode编码使用得广泛。

2.3. GBK系列

计算机发明之处及后面很长一段时间,只用应用于美国及西方一些发达国家,ASCII能够很好满足用户的需求。但是当天朝也有了计算机之后,为了显示中文,必须设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。

GBK和UTF8的区别:GBK就是在保存你的帖子的时候,一个汉字占用两个字节。。外国人看会出现乱码,此为我中华为自己汉字编码而形成之解决方案。
UTF8就是在保存你的帖子的时候,一个汉字占用3个字节。。但是外国人看的话不会乱码,此为西人为了解决多字节字符而形成之解决方案。

底层的算法咱们不用去了解得太深。

2.4.ISO系列

ASCII对英语国家是够用了,但对其他西欧国家却不够用,因此,人们将ASCII扩展到0-255的范围,形成了ISO-8859-1字符集(没有汉字)。值得一提的是,因为考虑到程序中处理的信息大多是西文信息,因此有些WEB容器(如:Tomcat4.x)在处理所接收到的request字符串时,如果您没指定request的编码方式则系统就缺省地采用ISO-8859-1

历史上,在国际标准化组织研究ISO10646标准的同时,另一个由多语言软件制造商组成的协会也在从事创立单一字符集的工作,这就是现在人们熟知的 Unicode。幸运的是,1991年前后ISO10646和Unicode的参与者都认识到,世界上不需要两个不同的单一字符集。他们合并双方的工作成果,并为创立单一编码表而协同工作。两个项目仍都存在并独立地公布各自的标准,都同意保持ISO10646和Unicode的码表兼容,并紧密地共同调整任何未来的扩展。

所以我们就可以简单地认为ISO10646就是Unicode

3.GBK和UTF-8怎么选:

如果你主要做中文程序的开发,客户也主要是中国人的话就用GBK吧,因为UTF-8编码的中文使用了三个字节,用GBK节省了空间。
如果做英文网站开发,还是用UTF-8吧,因为UTF-8英文只占一个字节。GBK英文也是两个字节的,并且国外客户访问GBK要下载语言包。如果你的网站是中文的,但国外用户也不少,最好也用UTF-8的吧。

3.1 面试题,一个汉字占几个字节/h3>

不要傻傻地回答一个汉字2个字节了。
标准答案:GBK编码环境下占2个字节。 UTF-8环境下占1-4个字节。

4.java开发中,怎么知道系统默认的编码格式/h2>

5.java开发中,怎么判断乱码字符串的编码/h2>

6.java开发中,怎么改变字符串的编码/h2>

好了 基本已经讲完,欢迎大家评论区指出不足,一起学习进步!

大家看完了点个赞,码字不容易啊。。。

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91462 人正在系统学习中

来源:易柏州Innovation

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年11月13日
下一篇 2021年11月13日

相关推荐