《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一2.2.4 字符编码方式

简介: 本节书摘来华章计算机《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一书中的第2章 ,第2.2.4节,[美] 凯S.霍斯特曼(Cay S. Horstmann) 著陈昊鹏 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2.4 字符编码方式
输入和输出流都是用于字节序列的,但是在许多情况下,我们希望操作的是文本,即字符序列。于是,字符如何编码成字节就成了问题。
Java针对字符使用的是Unicode标准。每个字符或“编码点”都具有一个21位的整数。有多种不同的字符编码方式,也就是说,将这些21位数字包装成字节的方法有多种。
最常见的编码方式是UTF-8,它会将每个Unicode编码点编码为1到4个字节的序列(请参阅表2-1)。UTF-8的好处是传统的包含了英语中用到的所有字符的ASCII字符集中的每个字符都只会占用一个字节。
image

另一种常见的编码方式是UTF-16,它会将每个Unicode编码点编码为1个或2个16位值(请参阅表2-2)。这是一种在Java字符串中使用的编码方式。实际上,有两种形式的UTF-16,被称为“高位优先”和“低位优先”。考虑一下16位值0x2122。在高位优先格式中,高位字节会先出现:0x21后面跟着0x22。但是在低位优先格式中,是另外一种排列方式:0x22 0x21。为了表示使用的是哪一种格式,文件可以以“字节顺序标记”开头,这个标记为16位数值0xFEFF。读入器可以使用这个值来确定字节顺序,然后丢弃它。
image

警告:有些程序,包括Microsoft Notepad(微软记事本)在内,都在UTF-8编码的文件开头处添加了一个字节顺序标记。很明显,这并不需要,因为在UTF-8中,并不存在字节顺序的问题。但是Unicode标准允许这样做,甚至认为这是一种好的做法,因为这样做可以使编码机制不留疑惑。遗憾的是,Java并没有这么做,有关这个问题的缺陷报告最终是以“will not f?ix(不做修正)”关闭的。对你来说,最好的做法是将输入中发现的所有先导的uFEFF都剥离掉。
除了UTF编码方式,还有一些编码方式,它们各自都覆盖了适用于特定用户人群的字符范围。例如,ISO 8859-1是一种单字节编码,它包含了西欧各种语言中用到的带有重音符号的字符,而Shift-JIS是一种用于日文字符的可变长编码。大量的这些编码方式至今仍在被广泛使用。
不存在任何可靠的方式可以自动地探测出字节流中所使用的字符编码方式。某些API方法让我们使用“默认字符集”,即计算机的操作系统首选的字符编码方式。这种字符编码方式与我们的字节源中所使用的编码方式相同吗?字节源中的字节可能来自世界上的其他国家或地区,因此,你应该总是明确指定编码方式。例如,在编写网页时,应该检查Content-Type头信息。

注意:平台使用的编码方式可以由静态方法Charset.defaultCharset返回。静态方法Charset.availableCharsets会返回所有可用的Charset实例,返回结果是一个从字符集的规范名称到Charset对象的映射表。
警告:Oracle的Java实现有一个用于覆盖平台默认值的系统属性f?ile.encoding。但是它并非官方支持的属性,并且Java库的Oracle实现的所有部分并非都以一致的方式处理该属性,因此,你不应该设置它。

StandardCharsets类具有类型为Charset的静态变量,用于表示每种Java虚拟机都必须支持的字符编码方式:
image

为了获得另一种编码方式的Charset,可以使用静态的forName方法:
image

在读入或写出文本时,应该使用Charset对象。例如,我们可以像下面这样将一个字节数组转换为字符串:
image

提示:有些方法允许我们用一个Charset对象或字符串来指定字符编码方式。由于选择的是StandardCharsets常量,所以无需担心拼写错误。例如,new String(bytes, "UTF 8") 就不可接受,并且会引发运行时错误。

警告:在不指定任何编码方式时,有些方法(例如String(byte[])构造器)会使用默认的平台编码方式,而其他方法(例如Files.readAllLines)会使用UTF-8。
相关文章
|
1月前
|
开发框架 Java API
最新Java基础系列课程--Day13-高级特性(二)
最新Java基础系列课程--Day13-高级特性
|
1月前
|
JSON fastjson 数据库
字符编码导致Rapidjson(腾讯开源的json解析库)到Fastjson(阿里开发的Java json解析库)转换失败的原因分析
最近在客户端的开发的过程中,使用到了RapidJson,公司的开发是客户端和数据库端都由不同的人进行开发,我负责的客户端的逻辑开发(使用c++),开发工具同时使用了VS2017和QT的编译环境,使用QT主要是为了客户端界面开发方便,而使用了VS环境主要是维护公司开发的数据库接口库,这个库的唯一作用就是作为一个中间桥梁,使用Rapidjson将数据库接口的json数据格式解析为结构体数据,从而在客户端界面进行展示,或者接收客户端的数据,使用Rapidjson将其转换为json数据,发送给数据库接口以保存数据使用 。不太明白的可以参考我上一篇文章说明Rapidjson的使用过程-Parse解析数组
22 0
|
1月前
|
Java 程序员 API
最新Java基础系列课程--Day13-高级特性(三)
最新Java基础系列课程--Day13-高级特性
|
1月前
|
开发框架 Java 程序员
最新Java基础系列课程--Day13-高级特性(一)
最新Java基础系列课程--Day13-高级特性
|
2月前
|
开发框架 Java 程序员
最新Java基础系列课程--Day13-高级特性
最新Java基础系列课程--Day13-高级特性
|
2月前
|
存储 Java 编译器
《Java 核心技术卷1 基础知识》第三章 Java 的基本程序设计结构 笔记(下)
《Java 核心技术卷1 基础知识》第三章 Java 的基本程序设计结构 笔记
78 0
|
2月前
|
存储 自然语言处理 Java
《Java 核心技术卷1 基础知识》第三章 Java 的基本程序设计结构 笔记(上)
《Java 核心技术卷1 基础知识》第三章 Java 的基本程序设计结构 笔记
76 0
|
2月前
|
Oracle Java 关系型数据库
《Java 核心技术卷1 基础知识》第二章 Java 程序设计环境 笔记
《Java 核心技术卷1 基础知识》第二章 Java 程序设计环境 笔记
29 1
|
2月前
|
存储 Java 编译器
《Java 核心技术卷1 基础知识》第一章 Java程序设计概述 笔记
《Java 核心技术卷1 基础知识》第一章 Java程序设计概述 笔记
40 0
|
2月前
|
Java API 容器
资深Java大牛带你由基础到原理再到项目实战,轻松掌控核心技术
《Java编程的逻辑》致力于帮助读者真正理解Java编程。对于每个语言特性和API,不仅介绍其概念和用法,还分析了为什么要有这个概念,实现原理是什么,背后的思维逻辑是什么;对于类库,分析了大量源码,使读者不仅知其然,还知其所以然,以透彻理解相关知识点。
资深Java大牛带你由基础到原理再到项目实战,轻松掌控核心技术