web-dev-qa-db-ja.com

ResourceBundleを使用してリソースプロパティでUTF-8を使用する方法

私はJavaのResourceBundleを使って私のリソースプロパティでUTF-8を使う必要があります。プロパティファイルに直接テキストを入力すると、mojibakeと表示されます。

私のアプリはGoogle App Engine上で動作します。

誰かが私に例をあげてもらえますか?私はこの仕事を手に入れることができません。

238
nacho

ResourceBundle#getBundle() は、.propertiesファイルが指定されている場合に PropertyResourceBundle を使用してカバーします。これは、デフォルトで Properties#load(InputStream) を使用して、これらのプロパティファイルをロードします。 javadoc に従って、デフォルトではISO-8859-1として読み取られます。

public void load(InputStream inStream) throws IOException

入力バイトストリームからプロパティリスト(キーと要素のペア)を読み取ります。入力ストリームは、load(Reader)で指定されている単純な行指向の形式であり、ISO 8859-1文字エンコーディングを使用すると想定されています。つまり、各バイトは1つのLatin1文字です。 Latin1以外の文字、および特定の特殊文字は、Java™言語仕様のセクション3.3で定義されているUnicodeエスケープを使用してキーおよび要素で表されます。

したがって、それらを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-エンコードUTF-8 text_utf8.properties text.properties

Eclipseなどの健全なIDEを使用する場合、Javaベースのプロジェクトで.propertiesファイルを作成し、Eclipse独自のエディターを使用すると、これは既に自動的に行われます。 Eclipseは、ISO-8859-1の範囲を超える文字を透過的に\uXXXX形式に変換します。以下のスクリーンショットも参照してください(下部の[プロパティ]タブと[ソース]タブに注意してください。クリックすると大きくなります)。

"Properties" tab"Source" tab

または、カスタムの ResourceBundle.Control 実装を作成することもできます。この実装では、 InputStreamReader を使用してUTF-8としてプロパティファイルを明示的に読み取り、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());

こちらもご覧ください:

356
BalusC

ResourceBundleのインスタンスがあり、Stringを取得できるのは、次のようにします。

String val = bundle.getString(key); 

私は私の日本語表示問題を解決しました:

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

これを見てください: 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をloadメソッドに適用します。

prop.load(isr);

ところで:。propertiesファイルからストリームを取得する:

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

ところで:InputStreamReaderからリソースバンドルを取得:

ResourceBundle rb = new PropertyResourceBundle(isr);

これがお役に立てば幸いです。

45
Chinaxing

たとえば、プロパティファイルがcp1251文字セットを使用している場合、UTF-8のResourceBundle.Controlおよび新しいStringメソッドは機能しません。

だから私は一般的な方法を使用することをお勧めします:Unicode記号で書きます。このため:

IDEA - 特別な " 透明なネイティブからASCIIへの変換 "オプション([設定]> [ファイルエンコーディング])。

Eclipse - プラグインがあります " Properties Editor "。それは別々のアプリケーションとして動作することができます。

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

UTF-8のリソースを含むresources.utf8ファイルを作成し、以下を実行するための規則を設定します。

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

この問題はついに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のファイルを再読み込みします。

15
stenix

注意:JavaプロパティファイルはISO 8859-1でエンコードする必要があります。

ISO 8859-1文字エンコードこのエンコーディングで直接表現できない文字は、Unicodeエスケープを使って書くことができます。エスケープシーケンスに使用できるのは、単一の「u」文字だけです。

@seeプロパティJava Doc

それでもこれをやりたいのであれば、以下を見てください。 EclipseでのJavaプロパティーUTF-8エンコード - いくつかのコード・サンプルがあります

8
Ralph

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

既に述べたように、プロパティファイルはISO 8859-1でエンコードされるべきです。

あなたはあなたのためにUnicode変換をするためにEclipse IDEのための上記のプラグインを使うことができます。

5
fmucar

これは、Guavaの優れたサポートライブラリとtry-with-resourcesコンストラクトを使ったJava 7のソリューションです。それは最も単純な全体的な経験のために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
}
3
Gary Rowe

ある人が示唆したように、私はリソースバンドルの実装を経験しました..しかしバンドルはen_USロケールの下でいつも呼ばれていたのでそれは助けになりませんでした。コントロールがen_USで呼び出されていました...ログメッセージを書き込もうとし、デバッグのステップを実行し、実行時にxhtmlおよびJSF呼び出しでロケールを変更した後に別のローカル呼び出しが行われていないか...それから私は私のサーバー(Tomcatサーバー)でファイルを読むためにutf8にシステムセットデフォルトをしようとしました..しかしそれはすべての私のクラスライブラリがutf8の下でコンパイルされなかったのでTomlecatはutf8フォーマットでそれから読み始めましたそしてサーバーが正常に動作していませんでした...そして私はxhtmlファイルから呼ばれるために私のJavaコントローラにメソッドを実装することになりました..そのメソッドで私は以下をしました:

        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フォーマットで保存しました、そしてそれは私のアプリケーションの各ユーザが参照ロケール設定を持っているのでそれはうまく働いています。

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");

私にとっての問題は、ファイル自体が間違ったエンコーディングになっていることです。 iconvを使って私のために働いた

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

設定/設定ダイアログを開きます(Ctrl + Alt + S)をクリックしてから、「エディタとファイルのエンコード」をクリックします。

Screenshot of window shown

次に、一番下に、プロパティファイルのデフォルトのエンコーディングを入力します。エンコードの種類を選択してください。

あるいは、リソースバンドルでテキストの代わりにUnicodeのシンボルを使用することもできます(たとえば、"ів"\u0456\u0432と等しくなります)。

私はRodによって提供されたアプローチを使用しようとしましたが、すべてのアプリケーションで同じ回避策を繰り返さないことについての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");
0
carlossierra