《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 数据挖掘 开发者
Java网络编程进阶:Socket通信的高级特性与应用
【6月更文挑战第21天】Java Socket通信是分布式应用的基础,涉及高级特性如多路复用(Selector)和零拷贝,提升效率与响应速度。结合NIO和AIO,适用于高并发场景如游戏服务器和实时数据分析。示例展示了基于NIO的多路复用服务器实现。随着技术发展,WebSockets、HTTP/2、QUIC等新协议正变革网络通信,掌握Socket高级特性为应对未来挑战准备。
|
2月前
|
XML Java API
你必须掌握的 21 个 Java 核心技术!,千峰Java
你必须掌握的 21 个 Java 核心技术!,千峰Java
|
28天前
|
存储 Java
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
23 0
|
2月前
|
安全 Java API
java的高级特性
Java的关键特性包括:跨平台能力,依赖JVM实现“一次编写,到处运行”;面向对象编程,通过类和对象抽象提高代码复用和维护性;内置安全机制如内存管理和异常处理;丰富的标准类库提供各种API;以及支持多线程,充分利用CPU资源。学习路线上,从基础的面向对象和类库使用开始,逐渐深入到多线程和高级特性。
24 1
|
1月前
|
存储 Java 编译器
Java核心技术第八章-泛型
Java核心技术第八章-泛型
|
1月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【6月更文挑战第18天】在Java中,Map的两大代表HashMap和TreeMap提供高效键值对操作。HashMap允许设定初始容量和加载因子以优化性能,非线程安全,可借助synchronized或ConcurrentHashMap处理多线程。遍历可通过entrySet()、keySet()和values()。而TreeMap依据键进行排序,支持自然排序和自定义Comparator,提供范围查询、获取首尾键的功能,适用于需有序遍历的场景。理解和利用这些特性能增强代码功能和效率。
|
2月前
|
Java API
Java从入门到精通:2.1.5深入学习Java核心技术之文件操作
Java从入门到精通:2.1.5深入学习Java核心技术之文件操作
|
2月前
|
Java API
Java从入门到精通:2.1.4深入学习Java核心技术——Java的输入输出流
Java从入门到精通:2.1.4深入学习Java核心技术——Java的输入输出流
|
2月前
|
IDE Java 程序员
Java程序员必备的21个核心技术,你都掌握了哪些?,深入浅出Java开发
Java程序员必备的21个核心技术,你都掌握了哪些?,深入浅出Java开发
|
2月前
|
消息中间件 存储 Java
Java从入门到精通:3.1.1掌握EJB、JPA、JMS等Java EE核心技术
Java从入门到精通:3.1.1掌握EJB、JPA、JMS等Java EE核心技术