Charset.defaultCharset()在JDK1.7和JDK 1.6下得到不同的结果

我正在测试我的应用程序的i18n兼容性。 我有一个英文版的Windows 7,这意味着系统的显示语言是英语。 我将系统区域设置为非unicode应用程序的中文。

我的应用程序在导出jdk1.6下的中文字符的Html文件时遇到问题,但在jdk1.7下运行时工作正常。

我调试它,发现直接原因是Charset.defaultCharset()返回了不同的值。

在jdk1.7下, Charset.defaultCharset()返回GBK ,这是中文的charset。

在jdk1.6下, Charset.defaultCharset()返回window_1252 ,这是拉丁语的charset。

我知道问题可以通过代码字符集来解决,比如utf-8

但我想知道为什么Charset.defaultCharset()在JDK1.7和JDK 1.6下返回不同的值。

Charset.defaultCharset()给出了JVM运行的字符集,因此它并不总是相同的值。 例如,如果您使用Netbeans运行程序,它将始终返回UTF-8,因为这是Netbeans中Java项目的默认编码。

我有类似于你的设置。 我的Windows是英文(菜单,对话框是英文),我使用土耳其语非Unicode应用程序。 当我在没有任何标志或系统参数的情况下启动JVM时,当Charset.defaultCharset()时,Java 7和Java 6运行时都会给出“CP1254”。 System.getProperty("file.encoding")和默认IO编码也是相同的。 (这两个Java版本的系统区域设置不同,但这是另一个故事。)

所以我猜你的问题是关于如何启动你的JVM,或者关于JVM如何决定它应该使用的默认编码。 如果您确定问题不是前者(您运行JVM时没有任何编码参数,并且您不尝试更改程序中任何位置的默认字符集),那么JVM会错误地获取默认编码,并且很可能是exception行为。

Java 7技术说明:

支持的编码在Java平台标准版7(Java SE 7)的不同实现之间有所不同。

Charset医生说:

Java虚拟机的每个实例都有一个默认的字符集,它可能是也可能不是标准字符集之一。 默认字符集在虚拟机启动期间确定,通常取决于底层操作系统使用的语言环境和字符集。

另外,我发现了一个关于在最终评估中使用-Dfile.encoding的“bug” :

这不是一个错误。 J2SE平台规范不要求“file.encoding”属性; 它是Sun实现的内部细节,不应由用户代码检查或修改。 它也是只读的; 在技​​术上不可能支持在命令行或程序执行期间的任何其他时间将此属性设置为任意值。

更改VM和运行时系统使用的默认编码的首选方法是在启动Java程序之前更改底层平台的区域设置。