我需要在我的资源属性中使用 Java 的ResourceBundle
. 当我将文本直接输入属性文件时,它显示为 mojibake。
我的应用在 Google App Engine 上运行。
谁能给我一个例子?我不能得到这个工作。
我需要在我的资源属性中使用 Java 的ResourceBundle
. 当我将文本直接输入属性文件时,它显示为 mojibake。
我的应用在 Google App Engine 上运行。
谁能给我一个例子?我不能得到这个工作。
从 Java 9 开始,属性文件默认编码为 UTF-8,并且使用 ISO-8859-1 之外的字符应该可以开箱即用。
指定文件时的幕后ResourceBundle#getBundle()
用途。这反过来又默认使用来加载这些属性文件。根据javadoc,它们默认读取为 ISO-8859-1。PropertyResourceBundle
.properties
Properties#load(InputStream)
public void load(InputStream inStream) throws IOException
从输入字节流中读取属性列表(键和元素对)。输入流采用 load(Reader) 中指定的简单的面向行的格式,并假定使用 ISO 8859-1 字符编码;也就是说,每个字节都是一个 Latin1 字符。非拉丁语1 中的字符和某些特殊字符使用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 - 编码 UTF-8 text_utf8.properties text.properties
.properties
在使用 Eclipse 等健全的 IDE 时,当您在基于 Java 的项目中创建文件并使用 Eclipse 自己的编辑器时,这已经自动完成。Eclipse 会透明地将超出 ISO-8859-1 范围的字符转换为\uXXXX
格式。另请参阅下面的屏幕截图(注意底部的“属性”和“源”选项卡,点击查看大图):
或者,您也可以创建一个自定义ResourceBundle.Control
实现,其中您使用 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());
假设您有一个 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);
顺便说一句:从.properties文件中获取流:
InputStream stream = this.class.getClassLoader().getResourceAsStream("a.properties");
顺便说一句:从以下位置获取资源包InputStreamReader
:
ResourceBundle rb = new PropertyResourceBundle(isr);
希望这可以帮到你 !
这个问题终于在 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 中的文件。
ResourceBundle.Control
例如,如果属性文件使用 cp1251 字符集,则使用 UTF-8 和新的 String 方法不起作用。
所以我推荐使用一个通用的方法:用 unicode符号写。为了这:
IDEA——有一个特殊的“ Transparent native-to-ASCII conversion ”选项(设置>文件编码)。
Eclipse - 有一个插件“属性编辑器”。它可以作为单独的应用程序工作。
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);
}
}
}
}
我们创建了一个包含 UTF-8 资源的 resources.utf8 文件,并有一个规则来运行以下内容:
native2ascii -encoding utf8 resources.utf8 resources.properties
注意:在Java <= 8中,Java 属性文件应以 ISO 8859-1 编码!
ISO 8859-1 字符编码。不能用这种编码直接表示的字符可以使用 Unicode 转义来编写;转义序列中只允许使用单个 'u' 字符。
@see 属性 Java 文档
如果您仍然真的想这样做:看看: Java 属性 Eclipse 中的 UTF-8 编码——有一些代码示例
由于Java 9:属性文件以UTF-8编码,所以应该没有问题/怀疑
在 Java SE 9 中,属性文件以 UTF-8 编码加载。在以前的版本中,ISO-8859-1 编码用于加载属性资源包。
http://sourceforge.net/projects/eclipse-rbe/
如前所述,属性文件应以 ISO 8859-1 编码
您可以使用 Eclipse IDE 的上述插件为您进行 Unicode 转换。
这是一个使用 Guava 出色的支持库和 try-with-resources 构造的 Java 7 解决方案。它使用 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
}
正如有人建议的那样,我完成了资源包的实现..但这并没有帮助..因为该包总是在 en_US 语言环境下调用...我试图将我的默认语言环境设置为另一种语言,但仍然是我的资源包实现正在使用 en_US 调用控制... ...然后我尝试将系统设置默认为 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;
}
我特别紧张,因为这可能会降低我的应用程序的性能......但是,在实现这个之后,看起来我的应用程序现在更快了......我认为这是因为,我现在直接访问属性而不是让JSF 解析访问属性的方式...我在此调用中特别传递布尔参数,因为我知道某些属性不会被翻译并且不需要采用 utf8 格式...
现在我已经以 UTF8 格式保存了我的属性文件,并且它工作正常,因为我的应用程序中的每个用户都有一个引用的区域设置首选项。
我的问题是文件本身的编码错误。使用 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");
Properties prop = new Properties();
String fileName = "./src/test/resources/predefined.properties";
FileInputStream inputStream = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
对于当前 (2021-2) Java 版本,仍然存在旧的 ISO-8859-1 函数utils.Properties#load。
请允许我引用官方文档。
属性资源包
PropertyResourceBundle 可以从 InputStream 或 Reader 构造,它表示一个属性文件。从 InputStream 构造 PropertyResourceBundle 实例要求输入流以 UTF-8 编码。默认情况下,如果在读取输入流时发生 MalformedInputException 或 UnmappableCharacterException,则 PropertyResourceBundle 实例将重置为异常之前的状态,重新读取 ISO-8859-1 中的输入流并继续读取。如果系统属性 java.util.PropertyResourceBundle.encoding 设置为“ISO-8859-1”或“UTF-8”,则输入流仅以该编码读取,如果遇到无效序列则抛出异常. 如果指定了“ISO-8859-1”,则无法以 ISO-8859-1 编码表示的字符必须由 Java™ 语言规范第 3.3 节中定义的 Unicode Escapes 表示,而采用 Reader 的其他构造函数则没有有这个限制。此系统属性忽略其他编码值。初始化此类时会读取和评估系统属性。初始化后更改或删除属性无效。
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/PropertyResourceBundle.html
属性#load
从输入字节流中读取属性列表(键和元素对)。输入流采用 load(Reader) 中指定的简单的面向行的格式,并假定使用 ISO 8859-1 字符编码;也就是说,每个字节都是一个 Latin1 字符。非拉丁语1 中的字符和某些特殊字符使用Java™ 语言规范第3.3 节中定义的Unicode 转义表示在键和元素中。
打开设置/首选项对话框 ( Ctrl+ Alt+ S),然后单击编辑器和文件编码。
然后,在底部,您将找到属性文件的默认编码。选择您的编码类型。
或者,您可以在资源包中使用 unicode 符号而不是文本(例如"ів"
equals \u0456\u0432
)
从 Java 9 开始,加载属性文件的默认值已更改为 UTF-8。https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9.htm