我需要使用UTF-8在我的资源属性使用Java的ResourceBundle。当我直接在属性文件中输入文本时,它显示为mojibake。
我的应用程序运行在谷歌应用程序引擎。
谁能给我举个例子?我找不到这份工作。
我需要使用UTF-8在我的资源属性使用Java的ResourceBundle。当我直接在属性文件中输入文本时,它显示为mojibake。
我的应用程序运行在谷歌应用程序引擎。
谁能给我举个例子?我找不到这份工作。
注意:在Java <= 8 Java属性文件应该编码在ISO 8859-1!
ISO 8859-1字符编码。 不能直接输入的字符 用这种编码表示可以 使用Unicode转义符编写;只有 允许输入一个“u”字符 转义序列。
Java文档
如果你真的想这样做:看看: Eclipse中的Java属性UTF-8编码——有一些代码示例
因为Java 9:属性文件是用UTF-8编码的,所以应该没有问题/疑问
在Java SE 9中,属性文件以UTF-8编码方式加载。在以前的版本中,ISO-8859-1编码用于加载属性资源包。
(https://docs.oracle.com/javase/9/intl/internationalization -改进- jdk 9. - htm # jsint guid - 9 - dcdb41c a989 - 4220 - 8140 - dbfb844a0fca)
Java 9及更新版本
从Java 9开始,属性文件默认编码为UTF-8,使用ISO-8859-1以外的字符应该可以开箱即用。
Java 8及以上版本
当指定了.properties文件时,ResourceBundle#getBundle()在封面下使用PropertyResourceBundle。这反过来使用默认的Properties#load(InputStream)来加载这些属性文件。根据javadoc,它们默认读取为ISO-8859-1。
public void load(InputStream stream)抛出IOException
从输入字节流中读取属性列表(键和元素对)。输入流采用load(Reader)中指定的简单的面向行的格式,并假定使用ISO 8859-1字符编码;即每个字节是一个拉丁字符。非拉丁字符1和某些特殊字符使用Java™语言规范3.3节中定义的Unicode转义符在键和元素中表示。
So, you'd need to save them as ISO-8859-1. If you have any characters beyond ISO-8859-1 range and you can't use \uXXXX off top of head and you're thus forced to save the file as UTF-8, then you'd need to use the native2ascii tool to convert an UTF-8 saved properties file to an ISO-8859-1 saved properties file wherein all uncovered characters are converted into \uXXXX format. The below example converts a UTF-8 encoded properties file text_utf8.properties to a valid ISO-8859-1 encoded properties file text.properties.
native2ascii -encoding UTF-8 text_utf8.properties text.properties
在使用Eclipse等正常的IDE时,当您在基于Java的项目中创建.properties文件并使用Eclipse自己的编辑器时,这已经自动完成了。Eclipse将透明地将超出ISO-8859-1范围的字符转换为\uXXXX格式。另见下面的截图(注意底部的“属性”和“源”选项卡,点击放大):
或者,您也可以创建一个定制的ResourceBundle。控件实现,其中您显式读取属性文件为UTF-8使用InputStreamReader,这样您就可以将它们保存为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 -如何得到正确的字符?
http://sourceforge.net/projects/eclipse-rbe/
如前所述,属性文件应该用ISO 8859-1编码
您可以使用上面的eclipse IDE插件为您进行Unicode转换。
我们创建了一个资源。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);
}
}
}
}
假设你有一个ResourceBundle实例,你可以通过以下方式获取String:
String val = bundle.getString(key);
我解决了我的日语显示问题:
return new String(val.getBytes("ISO-8859-1"), "UTF-8");
ResourceBundle。例如,如果属性文件使用cp1251字符集,则使用UTF-8和new String方法的控件将不起作用。
所以我建议使用一种常用的方法:使用unicode符号。:
IDEA -有一个特殊的“透明本机到ascii转换”选项(设置>文件编码)。
Eclipse——有一个插件“属性编辑器”。它可以作为单独的应用程序工作。
看这个: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应用到load方法:
prop.load(isr);
顺便说一句:从.properties文件中获取流:
InputStream stream = this.class.getClassLoader().getResourceAsStream("a.properties");
顺便说一句:从InputStreamReader获取资源包:
ResourceBundle rb = new PropertyResourceBundle(isr);
希望这能帮助到你!
下面是一个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
}
不管怎样,我的问题是文件本身的编码是错误的。使用iconv对我很有效
iconv -f ISO-8859-15 -t UTF-8 messages_nl.properties > messages_nl.properties.new
As one suggested, i went through implementation of resource bundle.. but that did not help.. as the bundle was always called under en_US locale... i tried to set my default locale to a different language and still my implementation of resource bundle control was being called with en_US... i tried to put log messages and do a step through debug and see if a different local call was being made after i change locale at run time through xhtml and JSF calls... that did not happend... then i tried to do a system set default to a utf8 for reading files by my server (tomcat server).. but that caused pronlem as all my class libraries were not compiled under utf8 and tomcat started to read then in utf8 format and server was not running properly... then i ended up with implementing a method in my java controller to be called from xhtml files.. in that method i did the following:
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格式保存了我的属性文件,它工作正常,因为我的应用程序中的每个用户都有一个引用的区域设置偏好。
我尝试使用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");
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中的文件。
打开设置/首选项对话框(Ctrl + Alt + S),然后单击编辑器和文件编码。
然后,在底部,您将找到属性文件的默认编码。选择您的编码类型。
或者,您可以在资源包中使用unicode符号而不是文本(例如“ів”等于\u0456\u0432)
从Java 9开始,加载属性文件的默认值已更改为UTF-8。https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9.htm
对于当前(2021-2)Java版本,仍然有旧的ISO-8859-1函数utils.Properties#load。
如果您使用属性。装载时必须使用ISO-8859-1。 如果使用ResourceBundle,那么UTF-8应该没问题。
请允许我引用官方文件。
PropertyResourceBundle
PropertyResourceBundle can be constructed either from an InputStream or a Reader, which represents a property file. Constructing a PropertyResourceBundle instance from an InputStream requires that the input stream be encoded in UTF-8. By default, if a MalformedInputException or an UnmappableCharacterException occurs on reading the input stream, then the PropertyResourceBundle instance resets to the state before the exception, re-reads the input stream in ISO-8859-1, and continues reading. If the system property java.util.PropertyResourceBundle.encoding is set to either "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding, and throws the exception if it encounters an invalid sequence. If "ISO-8859-1" is specified, characters that cannot be represented in ISO-8859-1 encoding must be represented by Unicode Escapes as defined in section 3.3 of The Java™ Language Specification whereas the other constructor which takes a Reader does not have that limitation. Other encoding values are ignored for this system property. The system property is read and evaluated when initializing this class. Changing or removing the property has no effect after the initialization.
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/PropertyResourceBundle.html
属性#负载
从输入字节流中读取属性列表(键和元素对)。输入流采用load(Reader)中指定的简单的面向行的格式,并假定使用ISO 8859-1字符编码;即每个字节是一个拉丁字符。非拉丁字符1和某些特殊字符使用Java™语言规范3.3节中定义的Unicode转义符在键和元素中表示。
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Properties.html加载(java.io.InputStream)