Java编码ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16 编码方式详解

简介: Java编码ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16 编码方式详解

1 ASCII

American Standard Code for Information Interchange。最早最通用的单字节编码系统,因为发明时间早,所以ASCII编码表的设计较为简单。

结构

  • ASCII表是单字节字符表,此表中一个(英文)字符用一个字节表示
  • 在ASCII中从00000000(第0个)~00011111(第31个)前32被用来作为控制字符表示各种类似:响铃、退格、换页等控制操作
  • 在ASCII中从00101111(第32个)~01111111(第127个)表示基本符号(!,@。%…)、数字(1,2,3…)、英文字母
  • ASCII表中一共有127个字符,后面的剩余空闲的字节没有被使用。


2 GB2312

GB2312是1981年开始实施的一套汉字处理的编码方案,GB是“国标”的意思,GB2312是对ASCII进行了扩展,在原来ASCII的基础上扩充了6000多个汉字和600多个其他字符,是我们使用的较早的一个汉字编码版本。

结构

GB2312用一个字节表示一个英文字符和一些基本符号和半角符号,用两个字节表示一个汉字和全角符号和一些我们日常使用的符号。

GB2312利用了ASCII的127个字符之后空余的部分,增添了6000多种常用汉字。

数值小于127的字节表示ASCII中原有字符,两个连续数值都大于127的字节表示一个汉字字符。

使用GB2312编码,当读取到一个数值上小于127的字节时当作一个ASCII中原有的字符处理。读到一个数值大于127的字节时会继续读取下一个字节,下一个字节的数值也必定是大于127,将两个大于127的字节一起组合形成一个字符。


3 GBK

GB2312有局限性,只能表示6000个字符,GBK是对GB2312的升级,GBK与GB2312非常相似,唯一的不同:

结构

使用GBK编码,当读取到一个数值上小于127的字节时当作一个ASCII中原有的字符处理。读到一个数值大于127的字节时必定会继续读取下一个字节,下一个字节的数值无需大于127,将两个字节一起组合形成一个汉字字符。

仅仅是一点微小的变化,让GBK在2312的基础上多增加了20000余个字符,GBK也是我们最常用的中文编码表。相比较UTF-8,GBK需要的空间小,如果我们工作的受众对象是汉语对象,使用GBK没有问题,但需注意java语言使用unicode编码,有可能会存在转换问题导致乱码,使用需谨慎。


4 Unicode

我们的GB2312和GBK都是在ASCII的基础上修改而来,利用了ASCII只使用127个字节的特点,而全世界其他的国家也是如此操作,导致了各个国家之间存在复杂的编码转换问题。而unicode的出现直接一次性扫清了所有障碍,原因很简单:unicode编码表中包含了世界上所有国家的所有字符和符号的编码。

unicode这种称呼是不专业的,这种统一世界的编码方式叫做:Universal Multiple-Octet Coded Character Set,简称:UCS。我们在习惯上将它叫做unicode。unicode编码是一种概念,在最新的规范中,所有的字符一概使用四个字节表示,网上有很多说unicode用两个字节表示一个字符是不对的,Unicode字符分为17组编排,0x0000 至 0xFFFF,而每平面拥有65536个码位,共1114112个。


5 UTF-8

unicode编码是一种概念,实际上真正实现了unicode编码的是被使用次数最多的UTF标准(UCS Transfer Format)。在UTF标准中现今最常用的是UTF-8。UTF-8是unicode编码的一种实现。

结构

UTF-8灵活性很强,用1~4个字节表示一个字符。

当字符在ASCII中可以被表示时,UTF-8编码方式就用一个字节来表示它。

在UTF-8中汉字用3个字符来表示。

unicode中所有的字符一概使用两个字节表示。从unicode到UTF-8并不是直接的对应,而是要过一些算法和规则来转换。


6 UTF-16

UTF-16不是简单的把UTF-8的范围扩大了一倍,UTF-16和UTF-8是彻底不同的两种编码概念。


结构

在绝大多数情况下,UTF-16中一个字符固定使用两个字节编码,一个字符两个字节是UTF-16编码的概念。

在极少数情况下也会出现三个字节表示一个字符的情况。

由于UTF-16固定使用两个字节表示一个字符,所以UTF-16不能与ASCII兼容。

在不同的机器中UTF-16存在因存储方式不同(大端法和小端法)导致数据有误,因此存在UTF16-LE和UTF16-BE两种UTF16的变体。

相比较UTF-8,在存储中文方面,UTF16更加结合空间。

UTF-16容错情况比UTF-8好,因为UTF-16稳定使用两个字节编码,如果数据错误不会连代其他数据被读错,而UTF-8是变长编码,可能导致后面的字符全部错误。

UTF-16广泛应用在各种系统中。


7 UTF-32

UTF-32可以说是“真正”的unicode编码,unicode用四个字节表示一个字符的特点在UTF-32中实现了,理论上这样根本不需要复杂的分配字节的方法,只需要每个字符一一对应即可,而且UTF-32的超大容量装得下任何的字符。但是问题也就在这里,一个字符需要四个字节太过于奢侈,UTF-32并不是一个很常用的编码方法。


目录
相关文章
|
16天前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
47 0
|
24天前
|
Java
Java系列之:字符串UTF-8 编码格式转换位 UTF-32 【生僻字截取问题】
这篇文章讨论了在Java中处理包含生僻字的字符串时可能遇到的问题,并提供了一种解决方法:将字符串的编码格式从UTF-8转换为UTF-32,以确保每个字符都占用固定的字节数,从而避免在截取操作中破坏字符,示例代码展示了如何进行编码转换和字符串截取。
|
29天前
|
存储 安全 Java
"Java编码魔法:揭秘图片与文件的Base64神秘转换术,让数据在指尖跳跃!"
【8月更文挑战第16天】Base64编码在Java开发中常用于将二进制数据如图片转换为ASCII字符串以便传输。编码使用64个字符及等号填充,每3字节数据编码为4个字符。Java利用`java.util.Base64`类实现此功能:读取图片或文件为字节数组后进行编码。解码时将Base64字符串还原为字节数组并写入文件。需注意编码效率降低、不提供安全性及特殊字符兼容性等问题。掌握这些技巧有助于解决Web开发中的数据传输需求。
52 4
|
14天前
|
Java PHP 开发者
PHP中的异常处理:Java常见的编码方式
在PHP开发中,掌握异常处理至关重要,它有助于预见并管理运行时错误,避免用户体验受损或数据丢失。本文介绍PHP异常处理的基本概念与实践,包括try-catch语句的使用,以及如何通过抛出和捕获异常来增强代码的健壮性和可靠性。通过示例展示如何避免常见错误,如除数为零的情况,并探讨多catch块和finally语句的高级用法,帮助开发者提升程序稳定性与可维护性。[总字符数:238]
21 0
|
11天前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
73 6
【Java学习】多线程&JUC万字超详解
|
4天前
|
Java 调度 开发者
Java并发编程:深入理解线程池
在Java的世界中,线程池是提升应用性能、实现高效并发处理的关键工具。本文将深入浅出地介绍线程池的核心概念、工作原理以及如何在实际应用中有效利用线程池来优化资源管理和任务调度。通过本文的学习,读者能够掌握线程池的基本使用技巧,并理解其背后的设计哲学。
|
4天前
|
缓存 监控 Java
Java中的并发编程:理解并应用线程池
在Java的并发编程中,线程池是提高应用程序性能的关键工具。本文将深入探讨如何有效利用线程池来管理资源、提升效率和简化代码结构。我们将从基础概念出发,逐步介绍线程池的配置、使用场景以及最佳实践,帮助开发者更好地掌握并发编程的核心技巧。
|
5天前
|
缓存 监控 Java
java中线程池的使用
java中线程池的使用
|
5天前
|
算法 Java 数据处理
Java并发编程:解锁多线程的力量
在Java的世界里,掌握并发编程是提升应用性能和响应能力的关键。本文将深入浅出地探讨如何利用Java的多线程特性来优化程序执行效率,从基础的线程创建到高级的并发工具类使用,带领读者一步步解锁Java并发编程的奥秘。你将学习到如何避免常见的并发陷阱,并实际应用这些知识来解决现实世界的问题。让我们一起开启高效编码的旅程吧!
|
10天前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。