编码方式规定了语言的最小单位用什么二进行制数字来表示,比如“UTF-8”编码中就有规定一个汉字用3个字节来表示,以及每个汉字对应哪3个字节。
java中的String是用来表示多国语言的,java支持的语言在对应的编码方式下都能找到相应的byte数字表示,但并不是任意的byte(或byte数组)都能对应到一个字--即使尝试所有的编码方式。String一定是有编码方式的,但文件不一定有,比如二进制文件。
Java中的编码方式一共有7种:
1、US-ASCII。7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁块2、ISO-8859-1。 ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1。
3、UTF-8。8 位 UCS 转换格式。
4、UTF-16BE。16 位 UCS 转换格式,Big Endian(最低地址存放高位字节)字节顺序。
5、UTF-16LE。16 位 UCS 转换格式,Little-endian(最高地址存放低位字节)字节顺序。
6、UTF-16。16 位 UCS 转换格式,字节顺序由可选的字节顺序标记来标识。
7、GBK。中文超大字符集。
java中的String默认的编码方式因机器而异,获取机器默认的编码方式用System.getProperty("file.encoding")。在我的机器上System.getProperty("file.encoding")的值为UTF-8,UTF-8和unicode是一一对应的。
String str="13陵";
byte[] arr=str.getBytes();
for(byte b:arr){
System.out.print(b+"\t");
}
System.out.println();
输出:49
51
-23
-103
-75
1对应49,3对应51,汉字“陵”对应3个字节:-23 -103 -75,这说明了str是按Unicode编码的。
当使用String.getBytes(String encoding)由字符串获得byte数组时,encoding指出希望以何种编码方式把String表示成byte[],不指定encoding时采用JDK默认的编码方式。
String str="13京陵";
byte[] arr=str.getBytes("ISO-8859-1");
for(byte b:arr){
System.out.print(b+"\t");
}
System.out.println();
输出:49 51 63 63
如果采用ISO-8859-1编码,所有汉字都用一个字节来表示,并且都是63。"?"的ASCII码刚好是63,因此国外的一些程序在国内中文环境下运行时经常出现乱码,上面布满了"?"。
当使用String(byte[] bytes, String encoding)构造字符串时,encoding所指的是bytes中的数据是按照那种方式编码的,而不是最后产生的String是什么编码方式。不指定encoding时采用JDK默认的编码方式。
String str="13陵";
byte[] arr=str.getBytes();
String str2=new String(arr,"GBK");
System.out.println(str2);
输出:13闄�
byte数组arr本来是按UTF-8编码,非要以"GBK"去读它,当然导致构建出来的String是乱码。GBK一个汉字用2个字节表示。
可以通过以下方式对String的编码方式进行转换:
String str_utf8="13京陵"; //用UTF-8编码的String
byte[] arr=str_utf8.getBytes("GBK"); //表示成用GBK编码的byte数组
String str_gbk=new String(arr,"GBK"); //再由byte数组来构建字符串
System.out.println(str_gbk);
输出:13京陵
对字符文件,这些文件是有编码方式的,可以用字符流(当然也可以用字节流)来读取,Java字符流都是Reader和Writer的子类,比如你使用InputStreamReader读取字符文件时,需要给InputStreamReader的构造函数传一个参数来指明文件编码方式,如果不写这个参数,则采用JDK默认的编码方式。
使用javac命令的时候需要指定java源文件的编码方式:javac -encoding "GBK" Test.java
对于一些二进制文件(比如加密后的文件)就只能用字节流进行读写了。
MySQl不支持Unicode,需要在连接字符串中指定编码方式为gb2312.
String connStr="jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=gb2312";
在Servlet开头加上两句:
response.setContentType("text/html;charset=UTF-8");
request.setChracterEncoding("UTF-8");
从HttpRequest中读参数时,利用reqeust.setCharacterEncoding()方法设置编码方式,读出的内容就是正确的了。
更多有关中文乱码或Java Web中涉及到的编码问题请参阅:http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/