Comment utiliser UTF-8 dans les propriétés de ressources avec ResourceBundle

j'ai besoin d'utiliser UTF-8 dans mes propriétés de ressource en utilisant le ResourceBundle de Java . Quand j'entre le texte directement dans le fichier de propriétés, il s'affiche comme mojibake.

mon application fonctionne sur Google App Engine.

quelqu'un Peut-il me donner un exemple? Je ne peux pas obtenir ce travail.

222
demandé sur Mechanical snail 2011-01-11 19:27:58

15 réponses

les ResourceBundle#getBundle() utilisations sous les couvertures PropertyResourceBundle lorsqu'un fichier .properties est spécifié. Cela utilise à son tour par défaut Properties#load(InputStream) pour charger ces fichiers de propriétés. Selon , le javadoc , ils sont par défaut lus comme ISO-8859-1.

public void load(InputStream inStream) throws IOException

lit une liste de propriétés (paires de clés et d'éléments) à partir de l'entrée de flux d'octets. Le flux d'entrée est dans un format simple orienté ligne tel que spécifié dans load(Reader) et est supposé utiliser le codage de caractères ISO 8859-1 ; c'est-à-dire que chaque octet est un caractère Latin1. Les caractères qui ne sont pas en Latin1, et certains caractères spéciaux, sont représentés dans les clés et les éléments en utilisant Unicode escapes comme défini dans la section 3.3 de la spécification de langage Java™.

donc, vous avez besoin de les sauver comme ISO-8859-1. Si vous avez des caractères au-delà de la plage ISO-8859-1 et que vous ne pouvez pas utiliser \uXXXX sur le dessus de la tête et que vous êtes donc forcé de sauver le fichier comme UTF-8, alors vous devez utiliser le native2ascii outil pour convertir un fichier de propriétés sauvé UTF-8 à un fichier de propriétés sauvé ISO-8859-1 dans lequel tous les caractères découverts sont convertis en \uXXXX format. L'exemple ci-dessous convertit un fichier de propriétés encodées UTF-8 text_utf8.properties en un fichier valide de propriétés codées ISO-8859-1 text.properties .

native2ascii -encoding UTF-8 text_utf8.properties text.properties

lorsque vous utilisez un IDE sain tel Qu'Eclipse, cela est déjà fait automatiquement lorsque vous créez un fichier .properties dans un projet basé sur Java et utilisez L'éditeur propre D'Eclipse. Eclipse convertira de façon transparente les caractères au-delà de la plage ISO-8859-1 au format \uXXXX . Voir aussi les captures d'écran ci-dessous (notez les onglets "propriétés" et "Source" en bas, Cliquez pour agrandir):

"Properties" tab "Source" tab

alternativement, vous pouvez également créer un personnalisé ResourceBundle.Control implémentation dans laquelle vous lisez explicitement les fichiers de propriétés comme UTF-8 en utilisant InputStreamReader , de sorte que vous pouvez simplement les sauver comme UTF-8 sans la nécessité de tracasser avec native2ascii . Voici un exemple de coup d'envoi:

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;
    }
}

peut être utilisé comme suit:

ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.text", new UTF8Control());

voir aussi:

328
répondu BalusC 2015-09-23 09:27:37

étant donné que vous avez une instance de ResourceBundle et que vous pouvez obtenir la chaîne de caractères par:

String val = bundle.getString(key); 

j'ai résolu mon problème D'affichage japonais par:

return new String(val.getBytes("ISO-8859-1"), "UTF-8");
116
répondu Rod 2013-05-17 13:29:05

regardez ça: http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load (java.io.Lecteur)

les propriétés acceptent un objet Reader comme argument, que vous pouvez créer à partir d'une entrée.

au moment de créer, vous pouvez spécifier le codage du lecteur:

InputStreamReader isr = new InputStreamReader(stream, "UTF-8");

ensuite appliquer ce lecteur à la méthode de la charge:

prop.load(isr);

BTW: obtenir le flux de .propriétés fichier:

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

j'espère que cela peut vous aider !

38
répondu Chinaxing 2016-02-08 15:08:56

nous créons une ressource.fichier utf8 qui contient les ressources dans UTF-8 et ont une règle pour exécuter ce qui suit:

native2ascii -encoding utf8 resources.utf8 resources.properties
17
répondu andykellr 2011-01-11 17:06:18
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
répondu marcolopes 2011-05-17 09:32:38

ResourceBundle.Control avec UTF-8 et les nouvelles méthodes de chaîne ne fonctionnent pas, si le fichier de propriétés utilise le jeu de caractères cp1251, par exemple.

donc j'ai recommandé en utilisant une méthode commune: écrire en unicode symboles. Pour ceci:

IDEA -- dispose d'une option spéciale conversion transparente natif en ASCII (réglages > encodage du fichier).

Eclipse -- a un plugin " Propriétés de l'Éditeur de " . Il peut fonctionner comme une application séparée.

17
répondu Kinjeiro 2016-11-29 13:40:02

Attention: les fichiers de propriétés java doivent être encodés en ISO 8859-1!

ISO 8859-1 de codage de caractères. Caractères qui ne peuvent pas être directement représenté dans ce codage peut être écrit en utilisant Unicode s'échappe ; seulement un seul caractère " u " est autorisé dans une séquence d'échappement.

@voir Propriétés Java Doc

Si vous voulez vraiment faire cela: jetez un oeil à: Java propriétés UTF-8 encodage dans Eclipse -- Il ya quelques échantillons de code

7
répondu Ralph 2017-05-23 11:55:00

ce problème a finalement été corrigé en Java 9: https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9

encodage par défaut pour les fichiers de propriétés est maintenant UTF-8.

la plupart des fichiers de propriétés existants ne doivent pas être affectés: UTF-8 et ISO-8859-1 ont le même encodage pour les caractères ASCII, et l'encodage ISO-8859-1 non ASCII lisible par un humain n'est pas valide UTF-8. Si un invalide La séquence D'octets UTF-8 est détectée, L'exécution Java relire automatiquement le fichier ISO-8859-1.

7
répondu stenix 2017-11-13 09:28:46

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

comme déjà indiqué, les fichiers de propriétés doivent être codés selon la norme ISO 8859-1

vous pouvez utiliser le plugin ci-dessus pour eclipse IDE pour faire la conversion Unicode pour vous.

5
répondu fmucar 2011-01-11 16:59:19

Voici une solution Java 7 qui utilise L'excellente bibliothèque de support de Guava et la construction try-with-resources. Il lit et écrit des fichiers de propriétés en utilisant UTF-8 pour l'expérience globale la plus simple.

pour lire un fichier de propriétés comme 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
  }
}

pour écrire un fichier de propriétés comme 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
}
2
répondu Gary Rowe 2014-03-20 15:25:55

comme l'un d'entre eux l'a suggéré, j'ai mis en œuvre un ensemble de ressources.. mais cela n'a pas aidé.. comme le paquet était toujours appelé sous en_US locale... j'ai essayé de définir ma locale par défaut à une langue différente et encore mon implémentation du contrôle du paquet de ressources était appelée avec en_US... j'ai essayé de mettre des messages de journalisation et de faire un pas à travers le débogage et voir si un appel local différent était fait après que j'ai changé de locale à l'heure d'exécution à travers les appels xhtml et JSF... qui n'a pas eu lieu... puis j'ai essayé de faire un jeu de système par défaut à un utf8 pour lire des fichiers par mon serveur (tomcat server).. mais cela a causé pronlem car toutes les bibliothèques de ma classe n'étaient pas compilées sous utf8 et tomcat a commencé à lire alors au format utf8 et le serveur ne fonctionnait pas correctement... puis j'ai fini par implémenter une méthode dans mon contrôleur java pour être appelé à partir de fichiers xhtml.. dans cette méthode, j'ai fait ce qui suit:

        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;
        }

j'étais particulièrement nerveux car cela pouvait ralentir l'exécution de mon application... cependant, après avoir implémenté ceci, il semble que mon application soit plus rapide maintenant.. je pense que c'est parce que, je suis maintenant accéder directement aux propriétés au lieu de laisser JSF parse son chemin dans l'accès aux propriétés... j'ai spécifiquement passer argument Booléen dans cet appel parce que je sais que certaines propriétés ne seraient pas traduits et n'ont pas besoin d'être en utf8 format...

maintenant j'ai sauvegardé mon fichier de propriétés au format UTF8 et il fonctionne très bien, car chaque utilisateur de mon application a une préférence de locale référente.

2
répondu Masoud 2015-09-30 17:48:03
Properties prop = new Properties();
String fileName = "./src/test/resources/predefined.properties";
FileInputStream inputStream = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
1
répondu Вассесуарий Пупочкин 2017-07-31 09:13:35

pour ce que ça vaut mon problème était que les fichiers eux-mêmes étaient dans le mauvais encodage. En utilisant iconv travaillé pour moi

iconv -f ISO-8859-15 -t UTF-8  messages_nl.properties > messages_nl.properties.new
0
répondu Zack Bartel 2014-12-02 02:35:12

j'ai essayé d'utiliser l'approche fournie par Rod, mais en tenant compte BalusC préoccupation de ne pas répéter le même travail dans toute la demande et est venu avec cette classe:

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;
        }
    }
}

la façon d'utiliser ceci serait très similaire à l'utilisation normale de la source de ressources:

private MyResourceBundle labels = new MyResourceBundle("es", "UTF-8");
String label = labels.getString(key)

ou vous pouvez utiliser le constructeur alternatif qui utilise UTF-8 par défaut:

private MyResourceBundle labels = new MyResourceBundle("es");
0
répondu carlossierra 2016-05-04 23:43:44

ouvrir la boîte de dialogue Paramètres / Préférences ( Ctrl + Alt + S ), puis cliquer éditeur et encodages de fichiers.

Screenshot of window shown

ensuite, en bas, vous trouverez les encodages par défaut pour les fichiers de propriétés. Choisissez votre type d'encodage.

vous pouvez aussi utiliser les symboles unicode au lieu du texte dans votre faisceau de ressources (par exemple "ів" égale \u0456\u0432 )

0
répondu Юра Чорнота 2018-04-12 16:47:02