在Eclipse中设置Java属性文件的UTF-8编码

50

最近我不得不将我正在开发的Web应用程序的编码从ISO-xx切换到utf8。一切都很顺利,除了属性文件。我在eclipse.ini中添加了-Dfile.encoding=UTF-8,普通文件工作正常。然而,属性文件显示出一些奇怪的行为。

如果我从Notepad++复制utf8编码的属性,并将它们粘贴到Eclipse中,它们可以正常显示和工作。但是当我重新打开属性文件时,我看到一些Unicode字符而不是正确的字符,如:

Zur\u00EF\u00BF\u00BDck instead of Zurück

应用程序仍能正常运行。

如果我开始编辑属性并添加一些特殊字符,然后保存,它们会显示正确,但它们不起作用,所有先前有效的特殊字符都不再起作用。

当我将本地版本与CVS进行比较时,我可以在远程文件上正确看到特殊字符,并在更新后重新开始:应用程序正常工作,但Eclipse显示Unicode字符。

我尝试通过右键单击文件并选择“其他:UTF8”来更改文件编码,但没有帮助。它还说:“从内容确定:ISO-8859-1”

我正在使用Java 6和基于Eclipse 3.3的Jboss开发者。

我可以通过在Notepad++中编辑属性并将它们粘贴到Eclipse中来解决问题,但如果有人能帮我修复Eclipse中的这个问题,我将不胜感激。

13个回答

69

"pre-Java-9"的答案如下。从Java 9开始,默认情况下以UTF-8格式保存和加载属性文件,但如果检测到无效的UTF-8字节序列,则会回退到ISO-8859-1。详情请参见Java 9发布说明


属性文件默认使用ISO-8859-1编码 - 可以查看Properties类的文档。

Spring提供了一个替代方案,可以使用指定的编码加载,使用PropertiesFactoryBean

编辑:正如Laurence在评论中指出的那样,Java 1.6引入了重载的loadstore方法,可以使用Reader/Writer创建文件的读取器。这意味着您可以使用任何编码创建文件的读取器,并将其传递给load方法。不幸的是,FileReader仍然无法在构造函数中指定编码(啊),因此您将被迫将FileInputStreamInputStreamReader链接在一起。但是,它会工作。

例如,使用UTF-8读取文件:

Properties properties = new Properties();
InputStream inputStream = new FileInputStream("path/to/file");
try {
    Reader reader = new InputStreamReader(inputStream, "UTF-8");
    try {
        properties.load(reader);
    } finally {
        reader.close();
    }
} finally {
   inputStream.close();
}

5
在Java 1.6中,您可以使用使用Reader/Writer方法而不是InputStream/OutputStream的方法来使用其他编码。 - Laurence Gonsalves
比起被接受的答案,这是一个更通用的解决方案,因此更好 :) - Radu Murzea
@JonSkeet 我已经为这个问题工作了几周。非常感谢你! - Fering
从Java 9+开始,属性文件应该使用UTF-8编码:https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9.htm#JSINT-GUID-974CF488-23E8-4963-A322-82006A7A14C7 - Rune Aamodt
1
@RuneAamodt:虽然我很高兴看到在阅读时仍支持ISO-8859-1。我会更新我的答案。 - Jon Skeet

54

3
这是一个非常实用的插件,感谢您的提示!很遗憾它没有安装网址,但只需将其放入插件文件夹即可。 - chesterbr
3
这个是否在内部使用native2ascii工具来处理非Unicode字符,还是我需要手动转义Unicode符号? - Ivaylo Slavov
@baybora.oren:我在Eclipse文件夹插件中扩展了.zip文件,但是在IDE中没有看到任何变化(我已经关闭并重新启动了Eclipse)。有什么提示吗? - Sefran2
@cricket 检查 Eclipse 版本,可能与您使用的 Eclipse 不兼容。 - bora.oren

12

这不是Eclipse的问题。如果您正在使用Properties类读取和存储属性文件,该类将转义所有特殊字符。

从类文档中可以看到:

在将属性保存到流中或从流中加载属性时,使用ISO 8859-1字符编码。对于不能直接表示为该编码的字符,使用Unicode转义;但是,在转义序列中只允许一个'u'字符。native2ascii工具可用于将属性文件转换为其他字符编码。

从API的store()方法中可以看到:

小于\u0020的字符和大于\u007E的字符将写为相应十六进制值xxxx的\uxxxx。


4
NetBeans可以很好地显示具有\uXXXX转义的属性文件,并使您能够正确显示UTF字符进行编辑。为什么Eclipse不行呢?在我看来,这是Eclipse存在的问题。 - Chrissi
+1:因为被skeet'd而感到的量子安慰 - rexford

11
Properties props = new Properties();
URL resource = getClass().getClassLoader().getResource("data.properties");         
props.load(new InputStreamReader(resource.openStream(), "UTF8"));

非常好用

:-)


不幸的是,在1.6中,props.load需要一个InputStream,并明确指出它期望旧式的ISO-8859-1。 - user153275

4
Properties props = new Properties();
URL resource = getClass().getClassLoader().getResource("data.properties");         
props.load(new InputStreamReader(resource.openStream(), "UTF8"));

这在Java 1.6中很有效。我该如何在1.5中实现此功能,因为Properties类没有解析InputStreamReader的方法。


4
您描述的过程中存在太多可能发生错误的点,所以我不会试图猜测您做错了什么,但我认为我知道在幕后发生了什么。 EF BF BDU+FFFD 的 UTF-8 编码形式,当解码器遇到格式不正确的输入时插入标准替换字符。听起来像是您的文本被保存为 ISO-8859-1,然后被读取为 UTF-8,再被保存为 UTF-8,最后使用平台默认编码(例如 windows-1252)使用 native2ascii 转换为 Properties 格式。
ü              => 0xFC                // 保存为 ISO-8859-1
0xFC           => U+FFFD              // 读取为 UTF-8
U+FFFD         => 0xEF 0xBF 0xBD      // 保存为 UTF-8
0xEF 0xBF 0xBD => \u00EF\u00BF\u00BD  // native2ascii
我建议您不要改变 "file.encoding" 属性。像 "file.separator" 和 "line.separator" 一样,它并没有你期望的那么有用。相反,养成在读写文本文件时始终指定编码的习惯。

4
有一个更简单的方法:
props.load(new InputStreamReader(new FileInputStream("properties_file"), "UTF8"));

3
你可以定义UTF-8 .properties文件来存储你的翻译,并使用ResourceBundle获取值。为了避免问题,你可以改变编码:
String value = RESOURCE_BUNDLE.getString(key); 
return new String(value.getBytes("ISO-8859-1"), "UTF-8");

3

1

这似乎只适用于某些字符...包括德语、葡萄牙语、法语的特殊字符。然而,我在处理俄语、印地语和汉语字符时遇到了麻烦。它们没有被转换为属性格式“native2ascii”,而是以 ?? ?? ?? 的形式保存。
我唯一能让我的应用程序正确显示这些字符的方法是将它们放入已翻译为UTF-8格式的属性文件中 - 如\u0915代替क,或\u044F代替я。 有什么建议吗?


您可以使用Spring的org.springframework.context.support.ReloadableResourceBundleMessageSource,它支持UTF-8编码的属性文件。我们在基于spring-mvc的Web应用程序中使用Spring来管理英语、德语、法语和中文的翻译。 - rexford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接