如何使用ResourceBundle在资源属性中使用UTF-8

我需要使用Java的ResourceBundle在我的资源属性中使用UTF-8。 当我直接input文本到属性文件,它显示为mojibake。

我的应用在Google App Engine上运行。

任何人都可以给我一个例子吗? 我无法得到这份工作。

当指定.properties文件时, ResourceBundle#getBundle()将在PropertyResourceBundle下面使用。 这反过来默认使用Properties#load(InputStream)来加载这些属性文件。 根据javadoc ,它们默认被读作ISO-8859-1。

public void load(InputStream inStream) throws IOException

从input字节stream中读取属性列表(键和元素对)。 inputstream采用简单的面向行的格式,如load(Reader)中所指定的, 并假定使用ISO 8859-1字符编码 ; 即每个字节是一个Latin1字符。 不在Latin1中的字符以及某些特殊字符在使用Unicode转义符的键和元素中表示,如“Java™语言规范”第3.3节中所定义。

所以,你需要把它们保存为ISO-8859-1。 如果你有超出ISO-8859-1范围的任何字符,并且你不能在头顶部使用\uXXXX ,那么你就不得不把这个文件保存为UTF-8,那么你需要使用native2ascii工具来将UTF-8保存的属性文件转换为ISO-8859-1保存的属性文件,其中将所有未被覆盖的字符转换为\uXXXX格式。 下面的示例将UTF-8编码的属性文件text_utf8.properties转换为有效的ISO-8859-1编码的属性文件text.properties

  native2ascii -encoding UTF-8 text_utf8.properties text.properties 

当使用像Eclipse这样的理性IDE时,在基于Java的项目中创build.properties文件并使用Eclipse自己的编辑器时,这已经自动完成了。 Eclipse将透明地将ISO-8859-1范围以外的字符转换为\uXXXX格式。 另请参见下面的截图(注意底部的“属性”和“源”标签,点击大):

“属性”选项卡 “来源”选项卡

或者,您也可以创build一个自定义的ResourceBundle.Control实现,其中您使用InputStreamReader显式读取属性文件为UTF-8,以便您可以将它们保存为UTF-8而无需与native2ascii 。 这是一个开球的例子:

 public class UTF8Control extends Control { public ResourceBundle newBundle (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { // The below is a copy of the default implementation. String bundleName = toBundleName(baseName, locale); String resourceName = toResourceName(bundleName, "properties"); ResourceBundle bundle = null; InputStream stream = null; if (reload) { URL url = loader.getResource(resourceName); if (url != null) { URLConnection connection = url.openConnection(); if (connection != null) { connection.setUseCaches(false); stream = connection.getInputStream(); } } } else { stream = loader.getResourceAsStream(resourceName); } if (stream != null) { try { // Only this line is changed to make it to read properties files as UTF-8. bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); } finally { stream.close(); } } return bundle; } } 

这可以使用如下:

 ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.text", new UTF8Control()); 

也可以看看:

  • Unicode – 如何获得正确的字符?

鉴于你有一个ResourceBundle的实例,你可以得到string通过:

 String val = bundle.getString(key); 

我解决了我的日本显示问题:

 return new String(val.getBytes("ISO-8859-1"), "UTF-8"); 

看看这个: http : //docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader)

属性接受一个Reader对象作为参数,你可以从InputStream创build它。

在创build时,您可以指定Reader的编码:

 InputStreamReader isr = new InputStreamReader(stream, "UTF-8"); 

然后将此Reader应用于加载方法:

 prop.load(isr); 

BTW:从.properties文件获取stream:

  InputStream stream = this.class.getClassLoader().getResourceAsStream("a.properties"); 

希望这可以帮助你!

我们创build一个包含UTF-8资源的resources.utf8文件,并有一个规则来运行以下命令:

 native2ascii -encoding utf8 resources.utf8 resources.properties 
 package com.varaneckas.utils; import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; /** * UTF-8 friendly ResourceBundle support * * Utility that allows having multi-byte characters inside java .property files. * It removes the need for Sun's native2ascii application, you can simply have * UTF-8 encoded editable .property files. * * Use: * ResourceBundle bundle = Utf8ResourceBundle.getBundle("bundle_name"); * * @author Tomas Varaneckas <tomas.varaneckas@gmail.com> */ public abstract class Utf8ResourceBundle { /** * Gets the unicode friendly resource bundle * * @param baseName * @see ResourceBundle#getBundle(String) * @return Unicode friendly resource bundle */ public static final ResourceBundle getBundle(final String baseName) { return createUtf8PropertyResourceBundle( ResourceBundle.getBundle(baseName)); } /** * Creates unicode friendly {@link PropertyResourceBundle} if possible. * * @param bundle * @return Unicode friendly property resource bundle */ private static ResourceBundle createUtf8PropertyResourceBundle( final ResourceBundle bundle) { if (!(bundle instanceof PropertyResourceBundle)) { return bundle; } return new Utf8PropertyResourceBundle((PropertyResourceBundle) bundle); } /** * Resource Bundle that does the hard work */ private static class Utf8PropertyResourceBundle extends ResourceBundle { /** * Bundle with unicode data */ private final PropertyResourceBundle bundle; /** * Initializing constructor * * @param bundle */ private Utf8PropertyResourceBundle(final PropertyResourceBundle bundle) { this.bundle = bundle; } @Override @SuppressWarnings("unchecked") public Enumeration getKeys() { return bundle.getKeys(); } @Override protected Object handleGetObject(final String key) { final String value = bundle.getString(key); if (value == null) return null; try { return new String(value.getBytes("ISO-8859-1"), "UTF-8"); } catch (final UnsupportedEncodingException e) { throw new RuntimeException("Encoding not supported", e); } } } } 

例如,如果属性文件使用cp1251字符集,则带有UTF-8的ResourceBundle.Control和新的String方法不起作用。

所以我推荐使用一种常用的方法: 用unicode符号写入 。 为了这:

IDEA – 有一个特殊的“ 透明本地到ASCII转换 ”选项(设置>文件编码)。

Eclipse – 有一个插件“ 属性编辑器 ” 。 它可以作为单独的应用程序。

注意:java属性文件应该在ISO 8859-1中编码!

ISO 8859-1字符编码。 在这种编码中不能直接表示的字符可以使用Unicode转义符来编写; 在转义序列中只允许一个“u”字符。

@请参阅属性Java文档

如果你仍然真的想这样做:看看: Eclipse中的Java属性UTF-8编码 – 有一些代码示例

http://sourceforge.net/projects/eclipse-rbe/

如前所述,属性文件应该在ISO 8859-1中进行编码

你可以使用上面的eclipse IDE插件为你做Unicode转换。

这是一个Java 7解决scheme,它使用了Guava的优秀支持库和try-with-resources构造。 它使用UTF-8读取和写入属性文件,获得最简单的整体体验。

以UTF-8读取属性文件:

 File file = new File("/path/to/example.properties"); // Create an empty set of properties Properties properties = new Properties(); if (file.exists()) { // Use a UTF-8 reader from Guava try (Reader reader = Files.newReader(file, Charsets.UTF_8)) { properties.load(reader); } catch (IOException e) { // Do something } } 

以UTF-8编写属性文件:

 File file = new File("/path/to/example.properties"); // Use a UTF-8 writer from Guava try (Writer writer = Files.newWriter(file, Charsets.UTF_8)) { properties.store(writer, "Your title here"); writer.flush(); } catch (IOException e) { // Do something } 
 Properties prop = new Properties(); String fileName = "./src/test/resources/predefined.properties"; FileInputStream inputStream = new FileInputStream(fileName); InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8"); 

Java 9中最终修复了这个问题: https : //docs.oracle.com/javase/9​​/intl/internationalization-enhancements-jdk-9

属性文件的默认编码现在是UTF-8。

大多数现有的属性文件不应该受到影响:UTF-8和ISO-8859-1对ASCII字符具有相同的编码,并且可读的非ASCII ISO-8859-1编码不是有效的UTF-8。 如果检测到无效的UTF-8字节序列,则Java运行时会自动重新读取ISO-8859-1中的文件。

对于我的问题是值得的是文件本身是在错误的编码。 使用iconv为我工作

 iconv -f ISO-8859-15 -t UTF-8 messages_nl.properties > messages_nl.properties.new 

正如一个人build议,我经历了资源包的实施..但这并没有帮助..因为该包总是在en_US语言环境下调用…我试图将我的默认语言环境设置为不同的语言,仍然是我的资源包控制被称为en_US …我试图把日志消息,并通过debugging,并通过调用xhtml和JSF调用运行时更改区域设置后,看看是否正在进行不同的本地调用…没有发生…然后我试图做一个默认的系统设置为UTF8读取我的服务器(tomcat服务器)的文件..但是这导致了pronlem,因为我所有的类库都没有在utf8下编译和tomcat开始阅读,然后以utf8格式和服务器没有正常运行…然后我结束了在我的Java控制器中实现一个方法从xhtml文件中调用..在该方法中,我做了以下几点:

  public String message(String key, boolean toUTF8) throws Throwable{ String result = ""; try{ FacesContext context = FacesContext.getCurrentInstance(); String message = context.getApplication().getResourceBundle(context, "messages").getString(key); result = message==null ? "" : toUTF8 ? new String(message.getBytes("iso8859-1"), "utf-8") : message; }catch(Throwable t){} return result; } 

我特别紧张,因为这可能会减慢我的应用程序的性能…但是,实施后,它看起来好像我的应用程序现在更快..我认为这是因为,我现在直接访问属性,而不是让JSFparsing它的方式访问属性…我明确地传递布尔参数在这个调用,因为我知道一些属性不会被翻译,不需要在UTF8格式…

现在我已经以UTF8格式保存了我的属性文件,并且工作正常,因为我的应用程序中的每个用户都有一个指示语言区域首选项。

我试图使用Rod提供的方法,但是考虑到BalusC关心在所有应用程序中不重复相同的解决方法,并且与这个类一起提供:

 import java.io.UnsupportedEncodingException; import java.util.Locale; import java.util.ResourceBundle; public class MyResourceBundle { // feature variables private ResourceBundle bundle; private String fileEncoding; public MyResourceBundle(Locale locale, String fileEncoding){ this.bundle = ResourceBundle.getBundle("com.app.Bundle", locale); this.fileEncoding = fileEncoding; } public MyResourceBundle(Locale locale){ this(locale, "UTF-8"); } public String getString(String key){ String value = bundle.getString(key); try { return new String(value.getBytes("ISO-8859-1"), fileEncoding); } catch (UnsupportedEncodingException e) { return value; } } } 

使用这种方法将会比常规的ResourceBundle用法非常类似:

 private MyResourceBundle labels = new MyResourceBundle("es", "UTF-8"); String label = labels.getString(key) 

或者你可以使用默认使用UTF-8的替代构造函数:

 private MyResourceBundle labels = new MyResourceBundle("es");