簡體   English   中英

如何從 Java 中的文件資源加載資源包?

[英]How to load a resource bundle from a file resource in Java?

我在c:/temp中有一個名為mybundle.txt的文件 -

c:/temp/mybundle.txt

如何將此文件加載到java.util.ResourceBundle 該文件是一個有效的資源包。

這似乎不起作用:

java.net.URL resourceURL = null;

String path = "c:/temp/mybundle.txt";
java.io.File fl = new java.io.File(path);

try {
   resourceURL = fl.toURI().toURL();
} catch (MalformedURLException e) {             
}           

URLClassLoader urlLoader = new URLClassLoader(new java.net.URL[]{resourceURL});
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle( path , 
                java.util.Locale.getDefault(), urlLoader );

只要您正確命名您的資源包文件(使用 .properties 擴展名),那么它就可以工作:

File file = new File("C:\\temp");
URL[] urls = {file.toURI().toURL()};
ClassLoader loader = new URLClassLoader(urls);
ResourceBundle rb = ResourceBundle.getBundle("myResource", Locale.getDefault(), loader);

其中“c:\temp”是保存屬性文件的外部文件夾(不在類路徑中),“myResource”與 myResource.properties、myResource_fr_FR.properties 等相關。

感謝http://www.coderanch.com/t/432762/java/java/absolute-path-bundle-file

當你說它是“一個有效的資源包”時——它是一個屬性資源包嗎? 如果是這樣,加載它的最簡單方法可能是:

try (FileInputStream fis = new FileInputStream("c:/temp/mybundle.txt")) {
  return new PropertyResourceBundle(fis);
}

1) 更改屬性的擴展名(例如 mybundle.properties。)
2) 將文件放入 jar 並將其添加到類路徑中。
3) 使用此代碼訪問屬性:

ResourceBundle rb = ResourceBundle.getBundle("mybundle");
String propertyValue = rb.getString("key");

來自ResourceBundle.getBundle(String baseName)的 JavaDocs:

baseName - 資源包的基本名稱,一個完全限定的類名

用簡單的英語來說,這意味着資源包必須在類路徑中,而baseName應該是包含包的包加上包名稱,在您的例子中是mybundle

省略擴展名和構成包名稱一部分的任何區域設置,JVM 將根據默認區域設置為您排序 - 有關更多信息,請參閱java.util.ResourceBundle上的文檔。

對於 JSF 應用程序

從給定文件路徑獲取資源包 prop 文件以在 JSF 應用程序中使用它們。

  • 為擴展 ResourceBundle 的類設置帶有 URLClassLoader 的包,以從文件路徑加載包。
  • loadBundle標簽的basename屬性中指定類。 <f:loadBundle basename="Message" var="msg" />

有關擴展 RB 的基本實現,請參閱示例自定義資源包中的示例

/* Create this class to make it base class for Loading Bundle for JSF apps */
public class Message extends ResourceBundle {
        public Messages (){
                File file = new File("D:\\properties\\i18n");  
                ClassLoader loader=null;
                   try {
                       URL[] urls = {file.toURI().toURL()};  
                       loader = new URLClassLoader(urls); 
                       ResourceBundle bundle = getBundle("message", FacesContext.getCurrentInstance().getViewRoot().getLocale(), loader);
                       setParent(bundle);
                       } catch (MalformedURLException ex) { }
       }
      .
      .
      .
    }

否則,從 getBundle 方法獲取包,但從Locale.getDefault()等其他來源獲取區域設置,在這種情況下可能不需要新的 (RB) 類。

如果像我一樣,你真的想從你的文件系統而不是類路徑加載 properties 文件,但除此之外保留所有與查找相關的智能,然后執行以下操作:

  1. 創建java.util.ResourceBundle.Control的子類
  2. 覆蓋newBundle()方法

在這個愚蠢的例子中,我假設你在C:\temp有一個文件夾,其中包含一個簡單的“.properties”文件列表:

public class MyControl extends Control {
@Override
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
        throws IllegalAccessException, InstantiationException, IOException {

    if (!format.equals("java.properties")) {
        return null;
    }

    String bundleName = toBundleName(baseName, locale);
    ResourceBundle bundle = null;

    // A simple loading approach which ditches the package      
    // NOTE! This will require all your resource bundles to be uniquely named!
    int lastPeriod = bundleName.lastIndexOf('.');

    if (lastPeriod != -1) {
        bundleName = bundleName.substring(lastPeriod + 1);
    }
    InputStreamReader reader = null;
    FileInputStream fis = null;
    try {

        File file = new File("C:\\temp\\mybundles", bundleName);

        if (file.isFile()) { // Also checks for existance
            fis = new FileInputStream(file);
            reader = new InputStreamReader(fis, Charset.forName("UTF-8"));
            bundle = new PropertyResourceBundle(reader);
        }
    } finally {
        IOUtils.closeQuietly(reader);
        IOUtils.closeQuietly(fis);
    }
    return bundle;
}

}

另請注意,這支持 UTF-8,我認為默認情況下不支持它。

這對我很有用。 而且它不會每次都重新加載包。 我試圖獲取一些統計信息來從外部文件位置加載和重新加載包。

File file = new File("C:\\temp");
URL[] urls = {file.toURI().toURL()};
ClassLoader loader = new URLClassLoader(urls);
ResourceBundle rb = ResourceBundle.getBundle("myResource", Locale.getDefault(), loader);

其中“c:\temp”是保存屬性文件的外部文件夾(不在類路徑中),“myResource”與 myResource.properties、myResource_fr_FR.properties 等相關。

注意:如果您的類路徑中有相同的包名稱,那么默認情況下將使用 URLClassLoader 的這個構造函數來獲取它。

感謝http://www.coderanch.com/t/432762/java/java/absolute-path-bundle-file

在下面找到一些統計數據,所有時間都以毫秒為單位。 我不擔心初始加載時間,因為這可能與我的工作區或我試圖弄清楚的代碼有關,但我想展示的是重新加載的方式較少,告訴我它來自內存。

這里有一些統計數據:

  • 初始 Locale_1 加載耗時 3486
  • 重新加載 Locale_1 用了 24
  • 重新加載 Locale_1 用了 23
  • 重新加載 Locale_1 用了 22
  • 重新加載 Locale_1 用了 15
  • 初始 Locale_2 加載耗時 870
  • 重新加載 Locale_2 耗時 22
  • 重新加載 Locale_2 耗時 18
  • 初始 Locale_3 加載耗時 2298
  • 重新加載 Locale_3 耗時 8
  • 重新加載 Locale_3 花費了 4

我更願意使用 resourceboundle 類來加載屬性 - 只是通過流、Properties 類和 load() 在一行而不是 5 行代碼中完成它。

供參考....

    public void init(ServletConfig servletConfig) throws ServletException {
    super.init(servletConfig);

    try {

            /*** Type1 */
        Properties props = new Properties();

        String fileName = getServletContext().getRealPath("WEB-INF/classes/com/test/my.properties");
    //          stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
    //          stream = ClassLoader.getSystemResourceAsStream("WEB-INF/class/com/test/my.properties");  

        InputStream stream = getServletContext().getResourceAsStream("/WEB-INF/classes/com/test/my.properties");

  //        props.load(new FileInputStream(fileName));
        props.load(stream);

        stream.close();
        Iterator keyIterator = props.keySet().iterator();
        while(keyIterator.hasNext()) {
                String key = (String) keyIterator.next();
                String value = (String) props.getProperty(key);
                System.out.println("key:" + key + " value: " + value);
        }

  /*** Type2:  */
  // Just get it done in one line by rb instead of 5 lines to load the properties
  // WEB-INF/classes/com/test/my.properties file            
  //            ResourceBundle rb = ResourceBundle.getBundle("com.test.my", Locale.ENGLISH, getClass().getClassLoader());
        ResourceBundle rb = ResourceBundle.getBundle("com.ibm.multitool.customerlogs.ui.nl.redirect");
        Enumeration<String> keys = rb.getKeys();
        while(keys.hasMoreElements()) {
            String key = keys.nextElement();
            System.out.println(key + " - " + rb.getObject(key));
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw new ServletException("Error loading config.", e);
    } catch (Exception e) {
        e.printStackTrace();
        throw new ServletException("Error loading config.", e);
    }       

}

我剛剛發布了一個名為Rincl的庫,它可以從資源文件加載中獲取所有苦差事。 將自動找到以類命名的資源文件(使用常規本地分辨率)。 更好的是,自動找到父類和接口的資源。 此外,它還具有各種優勢,例如透明地處理UTF-8屬性文件和XML屬性文件。

您還可以使用Rincl閱讀介紹或完整的國際化課程。

我認為您希望文件的級位於類路徑中,而不是實際文件本身。

試試這個(可能需要一些調整):

String path = "c:/temp/mybundle.txt";
java.io.File fl = new java.io.File(path);

try {
   resourceURL = fl.getParentFile().toURL();
} catch (MalformedURLException e) {
   e.printStackTrace();                     
}               

URLClassLoader urlLoader = new URLClassLoader(new java.net.URL[]{resourceURL});
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("mybundle.txt", 
                java.util.Locale.getDefault(), urlLoader );

如果您想加載不同語言的消息文件,只需使用 shared.loader= 的 catalina.properties ......有關更多信息,請訪問http://theswarmintelligence.blogspot.com/2012/08/use-resource-bundle-消息文件out.html

這對我有用:

File f = new File("some.properties");
Properties props = new Properties();
FileInputStream fis = null;
try {
    fis = new FileInputStream(f);
    props.load(fis);
} catch (FileNotFoundException e) {
    e.printStackTrace();                    
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fis != null) {
        try {
            fis.close();
            fis = null;
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    }
}           
public class One {

    private static One one = null;

    Map<String, String> configParameter = Collections.synchronizedMap(new HashMap<String, String>());

    private One() {
        ResourceBundle rb = ResourceBundle.getBundle("System", Locale.getDefault());

        Enumeration en = rb.getKeys();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            String value = rb.getString(key);
            configParameter.put(key, value);

        }
    }

    public static One getInstance() {
        if (one == null) {
            one= new One();
        }

        return one;

    }

    public Map<String, String> getParameter() {

        return configParameter;
    }



    public static void main(String[] args) {
        String string = One.getInstance().getParameter().get("subin");
        System.out.println(string);

    }
}
ResourceBundle rb = ResourceBundle.getBundle("service"); //service.properties
System.out.println(rb.getString("server.dns")); //server.dns=http://....

文件名應具有 .properties 擴展名,基本目錄應位於類路徑中。 否則它也可以在類路徑中的 jar 中相對於類路徑中的目錄,資源包可以用 / 或指定。 分隔器。 “。” 是首選。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM