Java与Unicode
Java的class文件采用utf8的编码方式,JVM运行时采用utf16。Java的字符串是unicode编码的。总之,Java采用了unicode字符集,使之易于国际化。
Java支持哪些字符集:
即Java能识别哪些字符集并对它进行正确地处理?查看Charset 类,最新的JDK支持160种字符集。可以通过static方法availableCharsets拿到所有Java支持的字符集。
assertEquals(160, Charset.availableCharsets().size());
Set<String> charsetNames =
Charset.availableCharsets().keySet();
assertTrue(charsetNames.contains("utf-8"));
assertTrue(charsetNames.contains("utf-16"));
assertTrue(charsetNames.contains("gb2312"));
assertTrue(Charset.isSupported("utf-8"));
|
需要在哪些时候注意编码问题?
1. 从外部资源读取数据:
这跟外部资源采取的编码方式有关,我们需要使用外部资源采用的字符集来读取外部数据:
InputStream is = new
FileInputStream("res/input2.data");
InputStreamReader streamReader = new InputStreamReader(is,
"GB18030");
|
这里可以看到,我们采用了GB18030编码读取外部数据,通过查看streamReader的encoding可以印证:
assertEquals("GB18030", streamReader.getEncoding());
|
正是由于上面我们为外部资源指定了正确的编码,当它转成char数组时才能正确地进行解码(GB18030 -> unicode):
char[] chars = new char[is.available()];
streamReader.read(chars, 0, is.available());
|
但我们经常写的代码就像下面这样:
InputStream is = new
FileInputStream("res/input2.data");
InputStreamReader streamReader = new InputStreamReader(is);
|
这时候InputStreamReader采用什么编码方式读取外部资源呢?Unicode?不是,这时候采用的编码方式是JVM的默认字符集,这个默认字符集在虚拟机启动时决定,通常根据语言环境和底层操作系统的 charset来确定。可以通过以下方式得到JVM的默认字符集:
Charset.defaultCharset();
|
为什么要这样?因为我们从外部资源读取数据,而外部资源的编码方式通常跟操作系统所使用的字符集一样,所以采用这种默认方式是可以理解的。
好吧,那么我通过我的IDE Ideas创建了一个文件,并以JVM默认的编码方式从这个文件读取数据,但读出来的数据竟然是乱码。为何?呵呵,其实是因为通过Ideas创建的文件是以utf-8编码的。要得到一个JVM默认编码的文件,通过手工创建一个txt文件试试吧。
2. 字符串和字节数组的相互转换
我们通常通过以下代码把字符串转换成字节数组:
但你是否注意过这个转换采用的编码呢?其实上面这句代码跟下面这句是等价的:
"string".getBytes(Charset.defaultCharset());
|
也就是说它根据JVM的默认编码(而不是你可能以为的unicode)把字符串转换成一个字节数组。
反之,如何从字节数组创建一个字符串呢?
new String("string".getBytes());
|
同样,这个方法使用平台的默认字符集解码字节的指定数组(这里的解码指从一种字符集到unicode)。
字符串编码迷思:
new String(input.getBytes("ISO-8859-1"), "GB18030")
|
上面这段代码代表什么?有人会说: “把input字符串从ISO-8859-1编码方式转换成GB18030编码方式”。如果这种说法正确,那么又如何解释我们刚提到的java字符串都采用unicode编码呢?
这种说法不仅是欠妥的,而且是大错特错的,让我们一一来分析,其实事实是这样的:我们本应该用GB18030的编码来读取数据并解码成字符串,但结果却采用了ISO-8859-1的编码,导致生成一个错误的字符串。要恢复,就要先把字符串恢复成原始字节数组,然后通过正确的编码GB18030再次解码成字符串(即把以GB18030编码的数据转成unicode的字符串)。注意,字符串永远都是unicode编码的。
但编码转换并不是负负得正那么简单,这里我们之所以可以正确地转换回来,是因为 ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为 String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来!
总结:
所以,我们在处理java的编码问题时,要分清楚三个概念:Java采用的编码:unicode,JVM平台默认字符集和外部资源的编码。
分享到:
相关推荐
给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 J 中的字母不重复,J 和 S中的所有字符都是字母。...
在本实验中,我们将深入探讨Java中的字符串处理,主要涉及两个方面:字符串基本操作和字符串比较。首先,我们从实验内容的第一个部分开始。 1. 输出字符串的长度、计数特定字符以及截取子字符串: 实验内容1要求...
标题中的“字符集编码的识别”是一个关于计算机科学和编程的重要主题,主要涉及文本数据在计算机内部的表示方式。...理解并熟练掌握字符集编码的识别和转换技巧,能帮助开发者避免许多与字符编码相关的难题。
VB字符转换:转换迅雷、快车、旋风下载地址,其实这下载地址的编码转换是很简单的,用的就是Base64网址编码转换。不同的是各自加了不同的字符。 迅雷就在地址前后分别加上“AA”和“ZZ”,然后进行Base64编码,...
C#日期格式字符串的相互转换操作是一个非常重要的知识点,在实际开发中,我们经常需要将日期格式字符串转换为DateTime类型的对象,或者将DateTime类型的对象转换为日期格式字符串。以下是C#日期格式字符串的相互转换...
base64编码的原理是将每3个字节(24位)的数据分为4个6位组,并为每个6位组分配一个字符,范围在'AA'到'ZZ'之间,以及'/'和'='。'='字符用于填充不足6位的数据。解码过程则相反,将这些字符转换回原始的二进制数据。...
java基础面试题字符串的排列提取方式是百度网盘分享地址
java基础面试题左旋转字符串提取方式是百度网盘分享地址
base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz
1. 肯尼迪总统的讲话假设:这是一道逻辑推理题,与Java编程技术无关,但可以考察逻辑思维能力。肯尼迪的讲话假设美国石油公司只关心利润,不顾政府的指示。 2. 专利意识与企业行为:此题考察的是对企业专利工作的...
对于包含中文字符的字符串来说,由于一个中文字符通常占据两个字节的位置(在某些编码下),因此在进行长度判断时需要特殊处理。下面我们将详细介绍如何使用C#来实现这一功能。 #### 方法实现分析 根据提供的代码...
通过不同的格式化字符串,我们可以将日期转换为所需的显示形式。 #### 二、格式化字符串详解 格式化字符串是控制日期显示样式的键值,下面列出了一些常用的格式化字符串及其含义: 1. **d (ShortDatePattern)**: ...
python串口发送数据与接收数据(文本转hex 接收字符串或者列表类型)
1. 字符串的创建和编码:在Python中,字符串可以通过单引号、双引号或三引号创建,并且支持Unicode编码,可以存储各种语言和特殊符号。 2. 字符串的连接和重复:通过加号(+)可以连接多个字符串,通过乘号(*)...
该项目为“studyjava-zz”设计源码,深入探索Java编程新视野,共计包含549个文件,涵盖209个Java源代码文件、74个Git忽略文件、70个项目配置文件、68个classpath文件、66个偏好设置文件、25个Markdown文档、16个XML...
通过以上知识点的学习,我们不仅了解了Java中字符串与字节数组之间的相互转换方法,还掌握了如何打印字节数组、查找字符或子字符串在字符串中的位置以及如何进行整型与字符串之间的转换。这些基本操作对于日常的Java...
根据提供的文件信息,我们可以深入探讨有关Python算法与数据结构中的字符串处理相关知识点。这段课程视频主要涉及Python语言在处理字符串时的各种技巧与方法,对于学习Python编程语言的同学来说,掌握这些知识点至关...
Java线程池是一种高效管理线程资源的工具,它的设计思想是基于生产者消费者模型,借鉴了工厂模式和代理模式的元素。线程池通过维护一组可重用线程,减少了创建和销毁线程的开销,提高了系统响应速度与并发处理能力。...
6. **数据传输**:可以发送和接收各种类型的数据,包括字节、字符、字符串等,满足不同应用场景的需求。 在压缩包"mfz-rxtx-2.2-20081207-win-x86x64"中,我们可以找到适用于32位和64位Windows系统的RXTX库文件。...
这两个函数在实现时考虑了中英文字符编码的不同,以确保截取后的内容能够正确显示。 第一个函数是`CutStr`,它的作用是截取给定字符串至最大长度,若超出最大长度,则在长度允许的范围内尽可能保留完整的中文字。该...