我需要使用Java的资源属性中使用UTF-8 ResourceBundle
。当我直接在属性文件中输入文本时,它显示为mojibake。
我的应用程序在Google App Engine上运行。
谁能给我一个例子吗?我无法完成这项工作。
java.util.ResourceBundle
而不是通过阅读java.util.Properties
。
我需要使用Java的资源属性中使用UTF-8 ResourceBundle
。当我直接在属性文件中输入文本时,它显示为mojibake。
我的应用程序在Google App Engine上运行。
谁能给我一个例子吗?我无法完成这项工作。
java.util.ResourceBundle
而不是通过阅读java.util.Properties
。
Answers:
该ResourceBundle#getBundle()
封面下使用PropertyResourceBundle
时,.properties
被指定的文件。默认情况下Properties#load(InputStream)
,这反过来使用它来加载那些属性文件。根据javadoc,默认情况下将其读取为ISO-8859-1。
public void load(InputStream inStream) throws IOException
从输入字节流中读取属性列表(键和元素对)。输入流采用load(Reader)中指定的面向行的简单格式,并假定使用ISO 8859-1字符编码;即每个字节都是一个Latin1字符。根据Java™语言规范第3.3节的定义,使用Unicode转义在键和元素中表示不在Latin1中的字符以及某些特殊字符。
因此,您需要将它们另存为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
当使用健全的IDE(例如Eclipse)时,.properties
在基于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());
StandardCharsets.UTF_8
如果您使用的是Java 7+,请随时使用
假设您有一个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创建该对象。
在创建时,您可以指定阅读器的编码:
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);
希望这可以帮到你 !
ResourceBundle
不过,这里的实际问题是关于。
Properties
并且想要检索UTF-8
String,则应该接受此答案,这就像一个符咒。然而,对于ResourceBundle
诸如语言资源这样的语言,那么可接受的答案是优雅的。尽管如此,还是投了赞成票。
ResourceBundle rb = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"))
ResourceBundle.Control
例如,如果属性文件使用cp1251字符集,则不能使用带有UTF-8和新String方法的方法。
因此,我推荐使用一种通用方法:用unicode编写符号。为了这:
IDEA-具有特殊的“ 透明的本机到ASCII转换 ”选项(“设置”>“文件编码”)。
Eclipse-有一个插件“ Properties Editor ”。它可以作为单独的应用程序工作。
这个问题终于在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中的文件。
我们创建一个resources.utf8文件,其中包含UTF-8中的资源,并具有运行以下规则:
native2ascii -encoding utf8 resources.utf8 resources.properties
native2ascii
从哪里得到?我只是做find / -name native2ascii*
了而没有任何结果,所以我认为它不仅仅是JDK的一部分...
jdk1.*.0_*/bin
。
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属性文件应使用ISO 8859-1编码!
ISO 8859-1字符编码。不能使用此编码直接表示的字符可以使用Unicode转义符编写;转义序列中仅允许使用一个'u'字符。
@see属性Java文档
如果您仍然真的想要这样做:看一下: 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
}
正如一个建议一样,我经历了资源包的实现..但这没有帮助..因为总是在en_US语言环境下调用资源包...我试图将默认语言环境设置为另一种语言,但仍然是我对资源包的实现使用en_US调用控件...我试图放置日志消息并进行调试,以查看在运行时通过xhtml和JSF调用更改语言环境后是否正在进行其他本地调用...这没有发生...然后我尝试将系统默认设置为utf8,以便通过我的服务器(tomcat服务器)读取文件。但这会导致问题,因为我的所有类库都没有在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
iconv
。我以前从未听说过它,但是我把它输入到控制台中,瞧,这确实存在(无论如何,在CentOS 6中。)
我尝试使用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符号代替资源包中的文本(例如"ів"
equals \u0456\u0432
)
从Java 9开始,默认的加载属性文件已更改为UTF-8。https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9.htm