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

我需要使用Java的ѭ0在我的资源属性中使用UTF-8。当我将文本直接输入属性文件时,它显示为mojibake。 我的应用在Google App Engine上运行。 谁能举个例子?我无法完成这项工作。     
已邀请:
当指定
.properties
文件时,
ResourceBundle#getBundle()
在封面
PropertyResourceBundle
下使用。这反过来默认使用
Properties#load(InputStream)
来加载这些属性文件。根据javadoc,它们默认为ISO-8859-1。   
public void load(InputStream inStream) throws IOException
     从输入字节流中读取属性列表(键和元素对)。输入流采用加载(Reader)中指定的简单的面向行的格式,并假设使用ISO 8859-1字符编码;即每个字节是一个Latin1字符。不是Latin1中的字符,以及某些特殊字符,使用“Java™语言规范”第3.3节中定义的Unicode转义符在键和元素中表示。 因此,您需要将它们保存为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的项目中创建
.properties
文件并使用Eclipse自己的编辑器时,这已经自动完成。 Eclipse将透明地将字符转换为ISO-8859-1范围以外的
uXXXX
格式。另请参见下面的屏幕截图(请注意底部的“属性”和“源”选项卡,单击以查看大图):   或者,您也可以创建一个自定义
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创建它。 在创建时,您可以指定Reader的编码:
InputStreamReader isr = new InputStreamReader(stream, "UTF-8");
然后将此Reader应用于加载方法:
prop.load(isr);
BTW:从.properties文件中获取流:
 InputStream stream = this.class.getClassLoader().getResourceAsStream("a.properties");
希望这可以帮到你 !     
例如,如果属性文件使用cp1251字符集,则使用UTF-8和新的String方法不起作用。 所以我推荐使用一种常见的方法:用unicode符号写。为了这: IDEA - 具有特殊的“透明原生到ASCII转换”选项(设置>文件编码)。 Eclipse - 有一个插件“属性编辑器”。它可以作为单独的应用程序。     
我们创建一个resources.utf8文件,其中包含UTF-8中的资源,并具有运行以下内容的规则:
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);  
            }  
        }  
    }  
}  
    
最终在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中的文件。     
注意:java属性文件应该用ISO 8859-1编码!   ISO 8859-1字符编码。   不能直接的字符   用这种编码表示的可以   使用Unicode转义编写;只要   允许使用单个'u'字符   一个逃脱序列。 @see Properties Java Doc 如果您仍然真的想这样做:看看: Eclipse中的Java属性UTF-8编码 - 有一些代码示例     
http://sourceforge.net/projects/eclipse-rbe/ 如前所述,属性文件应在ISO 8859-1中编码 您可以使用上面的eclipse IDE插件为您进行Unicode转换。     
这是一个Java 7解决方案,它使用了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
}
    
正如一个人建议的那样,我经历了资源包的实现..但这没有帮助..因为bundle总是在en_US语言环境下调用...我试图将我的默认语言环境设置为另一种语言,仍然是我的资源包的实现使用en_US调用控件...我试图放入日志消息并通过调试执行一步,看看在运行时通过xhtml和JSF调用更改语言环境之后是否正在进行另一个本地调用...没有发生...然后我试着通过我的服务器(tomcat服务器)将系统设置默认设置为utf8来读取文件..但是由于我的所有类库都没有在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;
        }
我特别紧张,因为这可能会降低我的应用程序的性能...但是,在实现之后,它看起来好像我的应用程序现在更快..我认为这是因为,我现在直接访问属性而不是让JSF解析它访问属性...我特意在这个调用中传递布尔参数,因为我知道一些属性不会被翻译,不需要是utf8格式... 现在我已经以UTF8格式保存了我的属性文件,并且它正常工作,因为我的应用程序中的每个用户都有一个参考区域设置首选项。     
Properties prop = new Properties();
String fileName = "./src/test/resources/predefined.properties";
FileInputStream inputStream = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
    
对于我的问题,我的问题是文件本身的编码错误。使用iconv为我工作
iconv -f ISO-8859-15 -t UTF-8  messages_nl.properties > messages_nl.properties.new
    
我尝试使用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");
    
打开“设置/首选项”对话框(Ctrl + Alt + S),然后单击“编辑器和文件编码”。 然后,在底部,您将对属性文件进行默认编码。选择您的编码类型。 或者,您可以在资源包中使用unicode符号而不是文本(例如
"ів"
等于
u0456u0432
)     

要回复问题请先登录注册