Как использовать UTF-8 в свойствах ресурсов с помощью ResourceBundle
Мне нужно использовать UTF-8 в свойствах ресурса с помощью Java ResourceBundle
. Когда я ввожу текст непосредственно в файл свойств, он отображается как mojibake.
Мое приложение работает в Google App Engine.
Может ли кто-нибудь дать мне пример? Я не могу получить эту работу.
Ответы
Ответ 1
ResourceBundle#getBundle()
использует под обложками PropertyResourceBundle
когда указан файл .properties
. Это, в свою очередь, использует по умолчанию Properties#load(InputStream)
для загрузки этих файлов свойств. Согласно javadoc, они по умолчанию читаются как ISO-8859-1.
public void load(InputStream inStream) throws IOException
Считывает список свойств (пары ключей и элементов) из потока входных байтов. Входной поток находится в простом линейно-ориентированном формате, как указано в load (Reader) , и предполагается использовать кодировку символов ISO 8859-1; то есть каждый байт является одним латинским символом. Символы не в Latin1 и некоторые специальные символы представлены в ключах и элементах, используя escape-последовательности Unicode, как определено в разделе 3.3 Спецификации языка Java ™.
Итак, вам нужно сохранить их как 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
При использовании надежной среды IDE, такой как Eclipse, это уже выполняется автоматически при создании файла .properties
в Java-проекте и использовании собственного редактора Eclipse. Eclipse будет прозрачно преобразовывать символы за пределы ISO-8859-1 в формат \uXXXX
. См. Также ниже скриншоты (обратите внимание на вкладки "Свойства" и "Источник" внизу, нажмите для увеличения):
!["Source" tab]()
В качестве альтернативы вы также можете создать пользовательскую 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());
См. также:
Ответ 2
Учитывая, что у вас есть экземпляр ResourceBundle, вы можете получить String:
String val = bundle.getString(key);
Я решил проблему с японским дисплеем:
return new String(val.getBytes("ISO-8859-1"), "UTF-8");
Ответ 3
посмотрите на это: 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");
надеюсь, что это может вам помочь!
Ответ 4
Мы создаем файл resources.utf8, который содержит ресурсы в UTF-8 и имеет правило для запуска следующего:
native2ascii -encoding utf8 resources.utf8 resources.properties
Ответ 5
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 native2ascii application, you can simply have
* UTF-8 encoded editable .property files.
*
* Use:
* ResourceBundle bundle = Utf8ResourceBundle.getBundle("bundle_name");
*
* @author Tomas Varaneckas <[email protected]>
*/
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);
}
}
}
}
Ответ 6
ResourceBundle.Control
с UTF-8 и новые методы String не работают, например, если файл свойств использует charset cp1251.
Поэтому я рекомендую использовать общий метод: писать в символах unicode. Для этого:
IDEA - имеет специальный параметр Transparent native-to-ASCII conversion" (Настройки > Файл Кодирование).
Eclipse - есть плагин Редактор свойств". Он может работать как отдельное приложение.
Ответ 7
Внимание: файлы свойств java должны быть закодированы в ISO 8859-1!
кодировка символов ISO 8859-1. Персонажи, которые не могут быть напрямую представленный в этой кодировке, может быть с использованием Unicode-экранов; только один символ "u" разрешен escape-последовательность.
@see Свойства Java Doc
Если вы все еще действительно хотите это сделать, посмотрите:
Свойства Java UTF-8 в Eclipse - есть примеры кода
Ответ 8
http://sourceforge.net/projects/eclipse-rbe/
поскольку уже указанные файлы свойств должны быть закодированы в ISO 8859-1
Вы можете использовать приведенный выше плагин для Eclipse IDE, чтобы преобразовать Юникод для вас.
Ответ 9
Здесь решение 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
}
Ответ 10
Properties prop = new Properties();
String fileName = "./src/test/resources/predefined.properties";
FileInputStream inputStream = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
Ответ 11
Эта проблема, наконец, была исправлена в 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.
Ответ 12
Для чего стоит моя проблема в том, что сами файлы были в неправильной кодировке. Использование iconv сработало для меня
iconv -f ISO-8859-15 -t UTF-8 messages_nl.properties > messages_nl.properties.new
Ответ 13
Как я уже сказал, я рассмотрел реализацию пакета ресурсов.. но это не помогло... поскольку пакет всегда вызывался под en_US locale... Я попытался установить языковой стандарт по умолчанию на другой язык, и все же моя реализация управления связью ресурсов вызывается с помощью en_US... я попытался поместить сообщения журнала и сделать шаг отладки и посмотреть, был ли произведен другой локальный вызов после того, как я изменил локаль во время выполнения через вызовы xhtml и JSF... что did not happend... тогда я попытался сделать системный набор по умолчанию для utf8 для чтения файлов на моем сервере (tomcat server).. но это вызвало пролема, поскольку все мои библиотеки классов не были скомпилированы под 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, и он отлично работает, поскольку каждый пользователь в моем приложении имеет предпочтение языковой референции.
Ответ 14
Я попытался использовать подход, предоставленный Родом, но с учетом заботы 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");