Java 将resourcebundle读取为UTF-8。getString()方法似乎将编码更改为ISO-8859

Java 将resourcebundle读取为UTF-8。getString()方法似乎将编码更改为ISO-8859,java,encoding,utf-8,properties,resourcebundle,Java,Encoding,Utf 8,Properties,Resourcebundle,我有一项光荣的任务,将我们整个工作区、项目和文件的编码改为UTF-8编码。我们有几个ResourceBundle,用于使用unicode编码特殊字符。我们还想通过切换到UTF-8来摆脱unicode,所以我也更改了Resourcebundles(.properties)文件的编码,并替换了unicode字符 我们也有德国的资源包和一些像 Ä,Ö,Ü,ß。ä,ö,ü以及“或”等特殊字符 未在浏览器中正确显示。例如: 资源绑定尝试: executeShellCommand.label=Shellko

我有一项光荣的任务,将我们整个工作区、项目和文件的编码改为UTF-8编码。我们有几个ResourceBundle,用于使用unicode编码特殊字符。我们还想通过切换到UTF-8来摆脱unicode,所以我也更改了Resourcebundles(.properties)文件的编码,并替换了unicode字符

我们也有德国的资源包和一些像

Ä,Ö,Ü,ß。ä,ö,ü以及“或”等特殊字符

未在浏览器中正确显示。例如:

资源绑定尝试:

executeShellCommand.label=Shellkommando ausführen

在浏览器中显示结果:

使用Java.util.ResourceBundle.getString(字符串键)方法读取ResourceBundle:

如果我检查上述Sysout的输出,我会得到以下结果:
getLocalizedString,key:executeShellCommand.label,resourcebundle:Shellkommando ausführen

似乎getString(key)方法在从bundle读取字符时将字符的编码更改为标准ResourceBundleEncoding(ISO-8859)

我试图解决这个问题:

    public String getLocalizedString(ResourceBundle bundle, String key) {
    try {
        System.out.println("getLocalizedString, key: " + key + ", resourcebundle: " + new String (bundle.getString(key).getBytes(), "UTF-8"));
        return new String (bundle.getString(key).getBytes(), "UTF-8");
    } catch (MissingResourceException e) {
        return key;
    } catch (UnsupportedEncodingException e) {
        return key;
    }
}
这有助于恢复最特殊的角色,但仍有许多角色未正确显示:

我还检查了WebApp的内容类型配置,以及获取资源包的每个请求的内容类型配置,所有内容都是utf-8


有人知道如何防止getString()方法更改编码吗?或者有更好的方法来解决这个问题吗?

Java ResourceBundle采用ISO-8859。我认为您需要使用属性而不是ResourceBundle

InputStream utf8in = getClass().getClassLoader().getResourceAsStream("/path/to/utf8.properties");
Reader reader = new InputStreamReader(utf8in, "UTF-8");
Properties props = new Properties();
props.load(reader);

这对黑客来说怎么样

public class HackClassLoader extends ClassLoader {

    public HackClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public InputStream getResourceAsStream(String name) {
        InputStream utf8in = getParent().getResourceAsStream(name);
        if (utf8in != null) {
            try {
                byte[] utf8Bytes = new byte[utf8in.available()];
                utf8in.read(utf8Bytes, 0, utf8Bytes.length);
                byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
                return new ByteArrayInputStream(iso8859Bytes);
            } catch (IOException ex) {
                throw new RuntimeException("Could not load " + name, e);
            } finally {
                utf8in.close();
            }
        }
        return null;
    }
}

ClassLoader hackLoader = new HackClassLoader(getClass().getClassLoader());
ResourceBundle bundle = ResourceBundle.getBundle("foo", Locale.UK, hackLoader);

如果您的ResourceBundle存储在属性文件中:Java默认情况下假定它们是以ISO-8859编码的。我已经通过检查输出找到了答案。但是有没有办法强制getString方法将字符读取为UTF-8而不是ISO-8859?我想在您的情况下,问题在您实例化ResourceBundle.Y之前就开始了您必须以ISO编码从流中读取;Java将其转换为字符串中的UTF-8,因此将字符串读取为UTF-8是正确的。(请参阅)是的,这正是我想要做的。但是PropertiesResourcebundle和Control类都没有任何更改读取编码格式的规范。是否有任何方法以UTF-8编码的方式打开捆绑包???使用自定义控件加载捆绑包:这是可行的,但需要更改从资源捆绑包读取的每种方法。我有很多。resourcebundles没有办法吗?我无法想象,由于这个问题,日本或中国的开发人员无法使用Bundle?我看到它有一个构造函数,它采用
java.io.Reader
。我猜你可以利用它。是的,我最终用这种方式解决了它。下面的代码解决了这个问题:@UweAllner也谢谢你。
java.io.InputStream applStream=getClass().getClassLoader().getResourceAsStream(applPath);Reader applReader=new InputStreamReader(applStream,“UTF-8”);applBundle=new PropertyResourceBundle(applReader)
这样做实际上会失去捆绑包的全部意义。捆绑包的好处在于
语言国家
文件中的属性可以覆盖
国家
文件中的属性,而这些属性也覆盖了基础文件。请看我的另一个答案。这是一个适当的攻击,但我认为您应该保留捆绑包另一种选择是将几个PropertyResourceBundle实例链接在一起(一个用于base、base_语言和base_语言国家/地区)。请参阅ResourceBundle.setParent().你说得对。在我选择资源之前,我必须询问当地语言,因此没有适当的行为。这不是解决问题的优雅方法。我检查你的黑客。伙计,如果我使用你的黑客,就找不到资源包。[31.07.14 19:02:19:279 CEST]000000 38 ServiceManage E E at.co.sbs.kixfs.util.Trace TraceeExceptionCapture异常\u Capture:java.util.MissingResourceException:在.co.sbs.operator.backend.resources.ApplicationResources上找不到捆绑包的资源,key dew您的属性文件在哪里?可能使用
getClass().getClassLoader()
而不是
Thread.currentThread().getContextClassloader()
public class HackClassLoader extends ClassLoader {

    public HackClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public InputStream getResourceAsStream(String name) {
        InputStream utf8in = getParent().getResourceAsStream(name);
        if (utf8in != null) {
            try {
                byte[] utf8Bytes = new byte[utf8in.available()];
                utf8in.read(utf8Bytes, 0, utf8Bytes.length);
                byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
                return new ByteArrayInputStream(iso8859Bytes);
            } catch (IOException ex) {
                throw new RuntimeException("Could not load " + name, e);
            } finally {
                utf8in.close();
            }
        }
        return null;
    }
}

ClassLoader hackLoader = new HackClassLoader(getClass().getClassLoader());
ResourceBundle bundle = ResourceBundle.getBundle("foo", Locale.UK, hackLoader);