Как использовать UTF-8 в свойствах ресурса с ResourceBundle - PullRequest
239 голосов
/ 11 января 2011

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

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

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

Ответы [ 15 ]

353 голосов
/ 11 января 2011

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

public void load(InputStream inStream) throws IOException

Считывает список свойств (пары ключей и элементов) из входного байтового потока. Входной поток имеет простой линейно-ориентированный формат, указанный в load (Reader) , и предполагается, что используется кодировка символов ISO 8859-1 ; то есть каждый байт является одним символом Latin1. Символы не на латинице 1 и некоторые специальные символы представлены в ключах и элементах с использованием экранирования 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());

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

125 голосов
/ 09 августа 2011

Учитывая, что у вас есть экземпляр ResourceBundle, и вы можете получить String следующим образом:

String val = bundle.getString(key); 

Я решил проблему с отображением на японском:

return new String(val.getBytes("ISO-8859-1"), "UTF-8");
45 голосов
/ 25 июля 2013

посмотрите на это: 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 file:

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

Кстати: получить комплект ресурсов из InputStreamReader:

ResourceBundle rb = new PropertyResourceBundle(isr);

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

20 голосов
/ 22 марта 2012

ResourceBundle.Control с UTF-8 и новыми методами String не работают, например, если в файле свойств используется кодировка cp1251.

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

IDEA - имеет специальный параметр " Прозрачное преобразование из нативного в ASCII " (Настройки> Кодировка файла).

Eclipse - имеет плагин " Редактор свойств " . Может работать как отдельное приложение.

19 голосов
/ 17 мая 2011
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);  
            }  
        }  
    }  
}  
17 голосов
/ 11 января 2011

Мы создаем файл resources.utf8, который содержит ресурсы в UTF-8 и имеет правило для запуска следующего:

native2ascii -encoding utf8 resources.utf8 resources.properties
16 голосов
/ 25 октября 2017

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

8 голосов
/ 11 января 2011

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

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

@ см. Свойства Java Doc

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

5 голосов
/ 11 января 2011

http://sourceforge.net/projects/eclipse-rbe/

, поскольку уже указанные файлы свойств должны быть закодированы в ISO 8859-1

. Вы можете использовать вышеуказанный плагин для Eclipse IDE, чтобы выполнить преобразование Unicode для вас.

3 голосов
/ 20 марта 2014

Вот решение на 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
}
...