java编码问题深入总结
2014-01-07 14:10
393 查看
Java语言能够这么普遍的应用,与其国际化的能力是 分不开的,国际化的编码是Java国际化中最重要的一个组成部分,Java的国际化编码能力与其使用Unicode编码是直接相关的。在Java中,任何 字符类型的数据在Java程序中均以Unicode字符表示,比如char、String等类型。
注:本文实验环境为Windows XP中文版和JDK1.5。
一、getBytes()
当Java程序从输入流、文件或字符文字量等途径获得字符串时,均会做字符编码的转换,例如InputStreamReader的构造函数中就需要指定编码方式,而对于从文件和字符文字量中获得字符串时,均采用系统默认的编码方式对字符数据进行解码。考虑下面一段代码:
语句①:将一个只含有一个字符“中”的字符串文字量赋给String类的一个对象str,字符文字量“中”是按照操作系统默认编码方式进行编码,在中文windows系统中通常是“GBK”, “中”在GBK编码中是0xD6D0,在将该字符赋给str时,Java会对该字符串进行编码转换,即将GBK编码方式的“中”转换成Unicode编码 方式的“中”,Unicode编码方式“中”的编码是0x4E2D,所以str在程序运行期间在内存中的二进制表示成16进制就是0x4E2D。
语句②:获得str字符串的二进制形式。getBytes(String encoding)方法需要指定编码方式,表示获得该字符串在何种编码方式中的二进制形式。此语句中没有设置参数,表示采用操作系统默认的编码方式,即此处获得的bytes是“中”在GBK编码中的二进制形式,即bytes[0]=0xD6, bytes[1]=0xD0。
语 句③:该语句与语句②的区别就是指定了编码方式,此处指定的是ISO-8859-1,即通常所说的Latin-1,该编码采用8bit对字符编码,所以编 码空间中只有256个字符。该编码中只包含了基本的ASCII码和一些扩展的其它西欧字符,所以该字符集中不可能包含中文的“中”字,也就是说Java虚 拟机无法在ISO-8859-1编码集中找到“中”字对应的编码,针对这种情况,就只返回一个问号(?,0x3f)字符,所以此时bytes.length只有1,且bytes[0]=0x3f。
二、new String(byte[] bytes, String encoding)
getBytes ()方法从字符串获得二进制的字节数组。如果要从二进制的字节数组获得字符串,则就需要使用new String(byte[] bytes, String encoding)方法,该方法按照encoding编码方法对字节数组bytes中的二进制数组进行解析,生成一个新的字符串对象。
语句①:定义一个字节数组。
语句②:将该字节数组中的二进制数据按照默认的编码方式(GBK)编码成字符串,我们知道GBK中0xD6 0xD0表示“中”,0x31表示字符“1”(GBK兼容ASCII,但不兼容ISO-8859-1除ASCII之外的部分),所以str得到的值是“中1”。
语句③:该句用ISO -8859-1编码方式对该字节数据进行编码,由于在ISO-8859-1编码方式中一个字节会被解析成一个字符,所以该字节数组会被解释成包含三个字符 的字符串,但由于在ISO-8859-1编码方式中没有对应0xD6和0xD0的字符,所以前两个字符会产生两个问号,由于0x31在ISO-8859- 1编码中对应字符“1”(ISO-8859-1也兼容ASCII),所以此语句得到str的值是“??1”。
三、编码转换
上面介绍的两个语句是解决Java中编码问题的基本语句,而且一般的乱码问题也都可以通过配合使用以上两个语句来解决。以下以几种典型情况为例来解释编码转换问题:
1. 将InputStream中以UTF-8编码方式编码的字符数据转换成为GBK编码的字节数组
注:本文实验环境为Windows XP中文版和JDK1.5。
一、getBytes()
当Java程序从输入流、文件或字符文字量等途径获得字符串时,均会做字符编码的转换,例如InputStreamReader的构造函数中就需要指定编码方式,而对于从文件和字符文字量中获得字符串时,均采用系统默认的编码方式对字符数据进行解码。考虑下面一段代码:
String str=”中”; | [align=center]①[/align] |
byte[] bytes = str.getBytes(); | [align=center]②[/align] |
bytes = str.getBytes(“ISO-8859-1”); | [align=center]③[/align] |
语句②:获得str字符串的二进制形式。getBytes(String encoding)方法需要指定编码方式,表示获得该字符串在何种编码方式中的二进制形式。此语句中没有设置参数,表示采用操作系统默认的编码方式,即此处获得的bytes是“中”在GBK编码中的二进制形式,即bytes[0]=0xD6, bytes[1]=0xD0。
语 句③:该语句与语句②的区别就是指定了编码方式,此处指定的是ISO-8859-1,即通常所说的Latin-1,该编码采用8bit对字符编码,所以编 码空间中只有256个字符。该编码中只包含了基本的ASCII码和一些扩展的其它西欧字符,所以该字符集中不可能包含中文的“中”字,也就是说Java虚 拟机无法在ISO-8859-1编码集中找到“中”字对应的编码,针对这种情况,就只返回一个问号(?,0x3f)字符,所以此时bytes.length只有1,且bytes[0]=0x3f。
二、new String(byte[] bytes, String encoding)
getBytes ()方法从字符串获得二进制的字节数组。如果要从二进制的字节数组获得字符串,则就需要使用new String(byte[] bytes, String encoding)方法,该方法按照encoding编码方法对字节数组bytes中的二进制数组进行解析,生成一个新的字符串对象。
byte[] bytes = {(byte)0xD6, (byte)0xD0, (byte)0x31}; | [align=center]①[/align] |
String str = new String(bytes); | [align=center]②[/align] |
str = new String(bytes,”ISO-8859-1”); | [align=center]③[/align] |
语句②:将该字节数组中的二进制数据按照默认的编码方式(GBK)编码成字符串,我们知道GBK中0xD6 0xD0表示“中”,0x31表示字符“1”(GBK兼容ASCII,但不兼容ISO-8859-1除ASCII之外的部分),所以str得到的值是“中1”。
语句③:该句用ISO -8859-1编码方式对该字节数据进行编码,由于在ISO-8859-1编码方式中一个字节会被解析成一个字符,所以该字节数组会被解释成包含三个字符 的字符串,但由于在ISO-8859-1编码方式中没有对应0xD6和0xD0的字符,所以前两个字符会产生两个问号,由于0x31在ISO-8859- 1编码中对应字符“1”(ISO-8859-1也兼容ASCII),所以此语句得到str的值是“??1”。
三、编码转换
上面介绍的两个语句是解决Java中编码问题的基本语句,而且一般的乱码问题也都可以通过配合使用以上两个语句来解决。以下以几种典型情况为例来解释编码转换问题:
1. 将InputStream中以UTF-8编码方式编码的字符数据转换成为GBK编码的字节数组
[align=left]public byte[] Transmit(InputStream UTFIStream)[/align] [align=left]{[/align] |
[align=left]BufferedReader reader = new BufferedReader(newInputStreamReader(UTFIStream),”UTF-8”);[/align] |
[align=left]StringBuffer content = new StringBuffer();[/align] |
[align=left]String temline;[/align] |
[align=left]while((temline=reader.readLine()) != null)[/align] |
[align=left]{[/align] |
[align=left] content.append(temline + “\n”);[/align] |
[align=left]}[/align] |
[align=left]return content.toString().getBytes(“GBK”);[/align] |
[align=left]}[/align] |
相关文章推荐
- 关于Java OutputStream 线程安全问题
- 转载: 《我为何停止使用Spring》 认同其中的一些感触和判断
- JDK安装与环境变量配置
- Eclipse开发工具学习之道:用Eclipse生成jar文件
- javaee6下测试hibernate时注意
- 网上找的一些有用的eclipse快捷键
- java获取机器名称
- java 获取当前应用程序和系统的属性特征,比如路径、用户名..
- HBase的Java Api连接失败的问题及解决方法
- 在Myeclipse安装Eclipse Color Themes插件
- Java数组实现冒泡排序
- HDFS中JAVA API的使用
- struts2笔记(一)HelloWorld
- Spring中报"Could not resolve placeholder"的解决方案
- 【黑马程序员】Java基础加强16:JDK1.5泛型
- java设计模式概述
- Java环境配置出现的问题及解决办法
- Maven 环境快速搭建二(eclipse+maven2+jetty)
- java中的上转型对象
- java中的上转型对象