Как использовать UTF-8 в свойствах ресурсов с помощью ResourceBundle

Мне нужно использовать UTF-8 в моих ресурсах с помощью ResourceBundle Java. Когда я ввожу текст непосредственно в файл свойств, он отображается как mojibake.

Мое приложение работает в Google App Engine.

Может ли кто-нибудь дать мне пример? Я не могу получить эту работу.

ResourceBundle#getBundle() использует под shellми PropertyResourceBundle когда указан файл .properties . Это, в свою очередь, использует по умолчанию Properties#load(InputStream) для загрузки этих файлов свойств. Согласно javadoc , они по умолчанию считываются как ISO-8859-1.

public void load(InputStream inStream) throws IOException

Считывает список свойств (пары ключей и элементов) из streamа входных байтов. Входной stream находится в простом линейно-ориентированном формате, как указано в 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 . См. Также ниже скриншоты (обратите внимание на вкладки «Свойства» и «Источник» внизу, нажмите для увеличения):

Вкладка «Свойства» Вкладка «Источник»

В качестве альтернативы вы также можете создать пользовательскую реализацию 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()); 

Смотрите также:

  • Unicode – Как правильно получить символы?

Учитывая, что у вас есть экземпляр 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); 

BTW: получить stream из файла .properties :

  InputStream stream = this.class.getClassLoader().getResourceAsStream("a.properties"); 

надеюсь, это поможет вам!

Мы создаем файл resources.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  */ 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.Control с UTF-8 и новыми методами String не работает, если файл свойств использует cs1251 charset, например.

Поэтому я рекомендую использовать общий метод: писать в символах Unicode . Для этого:

IDEA – имеет специальную опцию « Transparent native-to-ASCII conversion » («Настройки»> «Кодирование файлов»).

Eclipse – имеет плагин « Редактор свойств » . Он может работать как отдельное приложение.

Внимание: файлы свойств java должны быть закодированы в ISO 8859-1!

ISO 8859-1 кодировка символов. Символы, которые не могут быть непосредственно представлены в этой кодировке, могут быть записаны с помощью Unicode escapes; в escape-последовательности допускается только один символ «u».

@see Свойства Java Doc

Если вы все еще действительно хотите это сделать: посмотрите: свойства Java UTF-8 в Eclipse – есть примеры кода

Эта проблема, наконец, была исправлена ​​в 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.

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 locale … Я попытался установить локаль по умолчанию на другой язык и все еще моя реализация ресурсного пакета управление вызывалось с помощью en_US … я попытался поместить сообщения журнала и сделать шаг за отладкой и посмотреть, был ли произведен другой локальный вызов после изменения языкового стандарта во время выполнения через xhtml и JSF-вызовы … что не произошло … тогда я попытался сделать системный набор по умолчанию utf8 для чтения файлов на моем сервере (tomcat server) .. но это вызвало пронлема, поскольку все мои библиотеки classов не были скомпилированы под utf8, а tomcat начал читать затем в формате utf8 и сервер не работал должным образом … тогда я закончил с внедрением метода в моем java-controllerе, который вызывается из 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 

Я попытался использовать подход, предоставленный Родом, но с учетом заботы BalusC о том, чтобы не повторять одну и ту же работу во всем приложении и не приходил с этим classом:

 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 вместо текста в своем ресурсном пакете (например, "ів" равно \u0456\u0432 )

  • Формат Float до n знаков после запятой
  • Android-аудио FFT для получения определенной величины частоты с использованием аудиозаписей
  • Отправляйте SMS до тех пор,
  • Как сделать мою прикладную систему
  • BroadcastReceiver для ACTION_MEDIA_BUTTON не работает
  • Отражение для доступа к расширенным функциям телефонии
  • Java - чтение файла и разбиение на несколько файлов
  • Фрагмент добавить или заменить не работает
  • Обнаружение долгой печати с помощью Android
  • Как изменить десятичный разделитель DecimalFormat от запятой до точки / точки?
  • Java: необходимо каким-то образом сократить этот код
  • Давайте будем гением компьютера.