it-swarm.com.de

Verwendung von UTF-8 in Ressourceneigenschaften mit ResourceBundle

Ich muss UTF-8 in meinen Ressourceneigenschaften mit Javas ResourceBundle verwenden. Wenn ich den Text direkt in die Eigenschaftendatei eingebe, wird er als Mojibake angezeigt.

Meine App läuft auf Google App Engine.

Kann mir jemand ein Beispiel geben? Ich kann diese Arbeit nicht bekommen.

241
nacho

Das ResourceBundle#getBundle() wird unter dem Deckblatt PropertyResourceBundle verwendet, wenn eine .properties - Datei angegeben wird. Dies verwendet wiederum standardmäßig Properties#load(InputStream) , um diese Eigenschaftendateien zu laden. Gemäß the javadoc werden sie standardmäßig als ISO-8859-1 gelesen.

public void load(InputStream inStream) throws IOException

Liest eine Eigenschaftsliste (Schlüssel- und Elementpaare) aus dem Eingabebyte-Stream. Der Eingabestream hat ein einfaches zeilenorientiertes Format, wie in load (Reader) angegeben , und es wird davon ausgegangen, dass die ISO 8859-1-Zeichencodierung verwendet wird. Das heißt, jedes Byte ist ein Latin1-Zeichen. Zeichen, die nicht in Latin1 vorkommen, und bestimmte Sonderzeichen werden in Schlüsseln und Elementen mithilfe von Unicode-Escapezeichen dargestellt, wie in Abschnitt 3.3 der Java ™ -Sprachenspezifikation definiert.

Sie müssen sie also als ISO-8859-1 speichern. Wenn Sie Zeichen außerhalb des ISO-8859-1-Bereichs haben und nicht über Kopf \uXXXX Verwenden können und daher gezwungen sind, die Datei als UTF-8 zu speichern, müssen Sie verwenden das native2ascii Tool zum Konvertieren einer in UTF-8 gespeicherten Eigenschaftendatei in eine in ISO-8859-1 gespeicherte Eigenschaftendatei, in der alle nicht abgedeckten Zeichen in \uXXXX Format. Das folgende Beispiel konvertiert eine UTF-8-codierte Eigenschaftendatei text_utf8.properties In eine gültige ISO-8859-1-codierte Eigenschaftendatei text.properties.

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

Wenn Sie ein normales IDE wie Eclipse verwenden, geschieht dies bereits automatisch, wenn Sie eine .properties - Datei in einem Java) - basierten Projekt erstellen und verwenden Eclipse's eigener Editor: Eclipse wandelt die Zeichen außerhalb des ISO-8859-1-Bereichs transparent in das \uXXXX - Format um.

"Properties" tab"Source" tab

Alternativ können Sie auch eine benutzerdefinierte ResourceBundle.Control - Implementierung erstellen, in der Sie die Eigenschaftendateien explizit als UTF-8 mit InputStreamReader lesen Sie können sie einfach als UTF-8 speichern, ohne sich mit native2ascii herumschlagen zu müssen. Hier ist ein Kickoff-Beispiel:

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

Dies kann wie folgt verwendet werden:

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

Siehe auch:

356
BalusC

Vorausgesetzt, Sie haben eine Instanz von ResourceBundle und können String erhalten durch:

String val = bundle.getString(key); 

Ich habe mein japanisches Anzeigeproblem folgendermaßen gelöst:

return new String(val.getBytes("ISO-8859-1"), "UTF-8");
125
Rod

schauen Sie sich dies an: http://docs.Oracle.com/javase/6/docs/api/Java/util/Properties.html#load (Java.io.Reader)

die Eigenschaften akzeptieren ein Reader -Objekt als Argumente, die Sie aus einem InputStream erstellen können.

zum Zeitpunkt der Erstellung können Sie die Codierung des Readers festlegen:

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

wenden Sie dann diesen Reader auf die Lademethode an:

prop.load(isr);

Übrigens: Hole den Stream aus der . Properties Datei:

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

Übrigens: Hole Ressourcen-Bundle von InputStreamReader:

ResourceBundle rb = new PropertyResourceBundle(isr);

hoffe das kann dir helfen!

46
Chinaxing

ResourceBundle.Control mit UTF-8 und neuen String-Methoden funktioniert nicht, wenn die Eigenschaftendatei beispielsweise den Zeichensatz cp1251 verwendet.

Daher empfehle ich die Verwendung einer gängigen Methode: Schreibe in Unicode-Symbolen . Dafür:

[~ # ~] Idee [~ # ~] - hat eine spezielle " Transparente native-zu-ASCII-Konvertierung " Option (Einstellungen> Dateicodierung).

Eclipse - hat ein Plugin " Eigenschafteneditor ". Es kann als separate Anwendung arbeiten.

20
Kinjeiro
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 <[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);  
            }  
        }  
    }  
}  
19
marcolopes

Dieses Problem wurde in Java 9: https://docs.Oracle.com/javase/9/intl/internationalization-enhancements-jdk-9 behoben

Die Standardkodierung für Eigenschaftendateien ist jetzt UTF-8.

Die meisten vorhandenen Eigenschaftendateien sollten nicht betroffen sein: UTF-8 und ISO-8859-1 haben die gleiche Codierung für ASCII Zeichen, nicht aber für lesbare Nicht-ASCII-ISO-8859-1-Codierungen gültiges UTF-8 Wird eine ungültige UTF-8-Byte-Sequenz erkannt, liest die Java die Datei in ISO-8859-1 automatisch neu.

18
stenix

Wir erstellen eine resources.utf8-Datei, die die Ressourcen in UTF-8 enthält und die folgende Regel enthält:

native2ascii -encoding utf8 resources.utf8 resources.properties
17
andykellr

Achtung: Java Eigenschaftendateien sollten in ISO 8859-1 kodiert sein!

ISO 8859-1 Zeichenkodierung. Zeichen, die in dieser Codierung nicht direkt dargestellt werden können, können mit Unicode-Escapezeichen geschrieben werden. In einer Escape-Sequenz ist nur ein einziges 'u'-Zeichen zulässig.

@see Properties Java Doc

Wenn Sie dies dennoch wirklich tun möchten: Schauen Sie sich Folgendes an: Java-Eigenschaften UTF-8-Codierung in Eclipse - Es gibt einige Codebeispiele

8
Ralph

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

wie bereits erwähnt, sollten Eigenschaftendateien in ISO 8859-1 codiert werden

Sie können das obige Plugin für Eclipse IDE) verwenden, um die Unicode-Konvertierung für Sie vorzunehmen.

5
fmucar

Hier ist eine Java 7-Lösung, die Guavas hervorragende Unterstützungsbibliothek und das Try-with-Resources-Konstrukt verwendet. Es liest und schreibt Eigenschaftendateien mit UTF-8, um die einfachste Gesamterfahrung zu erzielen.

So lesen Sie eine Eigenschaftendatei als 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
  }
}

So schreiben Sie eine Eigenschaftendatei als 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
}
3
Gary Rowe

Wie vorgeschlagen, habe ich die Implementierung des Ressourcenpakets durchlaufen, aber das hat nicht geholfen, da das Paket immer unter dem Gebietsschema en_US aufgerufen wurde. Ich habe versucht, mein Standardgebietsschema auf eine andere Sprache und trotzdem die Implementierung des Ressourcenpakets festzulegen control wurde mit en_US aufgerufen ... Ich habe versucht, Protokollnachrichten zu platzieren und einen Schritt durch das Debugging zu machen, um festzustellen, ob ein anderer lokaler Aufruf erfolgt ist, nachdem ich das Gebietsschema zur Laufzeit durch xhtml- und JSF-Aufrufe geändert habe ... das ist nicht passiert ... dann habe ich versucht, ein System-Set-Default für das Lesen von Dateien von meinem Server (Tomcat-Server) auf utf8 zu setzen. Dies führte jedoch zu pronlem, da alle meine Klassenbibliotheken nicht unter utf8 kompiliert wurden und Tomcat begann, dann im utf8-Format zu lesen und Server lief nicht richtig ... dann endete ich mit der Implementierung einer Methode in meinem Java Controller aus XHTML-Dateien aufgerufen werden .. in dieser Methode habe ich Folgendes getan:

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

Ich war besonders nervös, da dies die Leistung meiner Anwendung verlangsamen könnte. Nach der Implementierung sieht es jedoch so aus, als ob meine Anwendung jetzt schneller ist. Ich glaube, das liegt daran, dass ich jetzt direkt auf die Eigenschaften zugreife, anstatt sie zu vermieten JSF parst seinen Weg in den Zugriff auf Eigenschaften ... Ich übergebe speziell das Boolesche Argument in diesem Aufruf, weil ich weiß, dass einige der Eigenschaften nicht übersetzt werden und nicht im utf8-Format vorliegen müssen ...

Jetzt habe ich meine Eigenschaftendatei im UTF8-Format gespeichert und es funktioniert einwandfrei, da jeder Benutzer in meiner Anwendung eine Voreinstellung für das Referenzgebietsschema hat.

2
Masoud
Properties prop = new Properties();
String fileName = "./src/test/resources/predefined.properties";
FileInputStream inputStream = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");

Für das, was es wert ist, war mein Problem, dass die Dateien selbst in der falschen Kodierung waren. Die Verwendung von iconv hat bei mir funktioniert

iconv -f ISO-8859-15 -t UTF-8  messages_nl.properties > messages_nl.properties.new
1
Zack Bartel

Öffnen Sie das Dialogfeld Einstellungen/Voreinstellungen (Ctrl + Alt + S), und klicken Sie dann auf Editor und Dateikodierungen.

Screenshot of window shown

Anschließend werden Sie unten die Standardcodierungen für Eigenschaftendateien festlegen. Wählen Sie Ihren Codierungstyp.

Alternativ können Sie Unicode-Symbole anstelle von Text in Ihrem Ressourcenpaket verwenden (z. B. "ів" entspricht \u0456\u0432)

Ich habe versucht, den Ansatz von Rod zu verwenden, aber unter Berücksichtigung der Bedenken von BalusC, dass nicht in der gesamten Anwendung die gleiche Problemumgehung wiederholt werden sollte, kam ich mit dieser Klasse:

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

Die Art und Weise, dies zu verwenden, wäre der normalen Verwendung von ResourceBundle sehr ähnlich:

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

Oder Sie können den alternativen Konstruktor verwenden, der standardmäßig UTF-8 verwendet:

private MyResourceBundle labels = new MyResourceBundle("es");
0
carlossierra