日期:2014-05-17  浏览次数:20864 次

Java默认字符编码与Windows系统语言设置
提起Java的字符编码及国际化问题,确实让人很头疼,几乎任何用到java的地方都会遇到他,而且表现出来又是多种多样的错误,让人头大。最近帮“博导”解决一个问题,又遇到了新的问题,System.out输出在Eclipse中是乱码,但是命令行可以正常显示。

    这个具体问题倒是不难理解,Eclipse中的输出结果是模拟了操作系统的控制台,而这个模拟的控制台采取什么编码显示字符就是由Eclipse来控制了,有可能和系统的控制台使用的不是一个字符编码,所以才会产生乱码的问题。经过测试,发现“博导”系统的控制面板里的“区域和语言选项”中“标准和格式”选的不是中国,而是一个西欧国家,系统默认的字符集是cp1252,所以输出时的编码是cp1252,在Eclipse的控制台里就是一堆乱码。

    整理一下对于java编码问题的认识:首先,是关于字符编码的知识,网上介绍的很多,而使用起来其实不需要知道编码的内部知识,知道有哪些编码和常用的匹配就可以了。

标准和格式 JVM默认字符集
中文(中国) GBK
中文(新加坡) GBK
中文(香港特别行政区) MS950
中文(澳门特别行政区) MS950
中文(台湾) MS950
    以上是windows中中文的相关默认字符集,可以看到只有两种,基本是按照政治因素分布的。这个默认字符集会影响到我们的哪些方面呢?

源代码编码。如果你使用的是记事本来编写你的代码,那么由于它是一个文本文件,它的默认编码会受制于系统的默认字符编码。在没有特别指定的前提下,一般是GBK。而使用Eclipse开发,我们可以在Eclipse的设置里将Editor的编码设为UTF-8,来做到国际化。
代码中的硬编码字符。这个应该说和上一个是一个问题,只不过因为表现得比较明显,权且单独提出来说。比如我在源代码里写入了“汉字”这两个字符(用记事本来写,采取默认字符集,下同),并用javac编译。此时当我修改了系统的“标注和格式”设定后,如果修改后使用的默认字符集和原来的字符以不同,就会产生乱码问题。因为编译之后,“汉字”是使用原来的字符集保存的,而输出时会按照这个编码输出,但是此时系统的默认字符集已经不是原来的那个了,自然就不能正常解析,会出现乱码。特别是当原来的编码是GBK这种非西文字符集(一般容量比较大),而修改后成为ASCII类似的小字符集时,由于不能表示出所有的字符,汉字一般都会被用??替代,说明这些字符的编码已经超出了当前字符集的表示范围。
其他。其实可能还有很多,但是本文只涉及到以上几点。


    粘一段我用来测试默认字符集的代码:



public class TestSystem { public static void main(String[] args) { System.out.println("?3?????-???|???? ????"+ System.getProperty("file.encoding")); System.out.println(new String("?3?????-???|???? ????" .getBytes("GBK"),System.getProperty("file.encoding"))+ System.getProperty("file.encoding"));   }



(苦死我了,php的编码问题我暂时还没辙)

    代码中GBK所代表的是当前(编译环境下)的系统默认字符集。编译之后,更改“标准和格式”,运行 java TestSystem就可以看到效果。第一行输出的是没有经过处理的汉字,会出现乱码。第二行是将汉字按照原始编码打散成Byte数组,然后按照当前系统默认字符集重组后的输出,不会出现乱码。这也是解决乱码问题的一个思路,就是利用String的String(byte[] bytes,String charsetName);方法来进行编码转换。另外,InputStream的构建方法里也可以指定字符编码,应该也是一个解决方法。

    总之,解决java的字符编码问题首先需要明确的是你的问题中涉及到哪些编码,当前默认编码(不一定是系统的,而是JVM的)是什么,然后才好利用各种解决方法来解决。

    希望以后不再被Java的字符编码问题所困扰,希望utf8可以一统天下!