【问题标题】:How to load a resource bundle from a file resource in Java?如何从 Java 中的文件资源加载资源包?
【发布时间】:2010-11-13 10:22:50
【问题描述】:

我在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 );

【问题讨论】:

    标签: java resourcebundle


    【解决方案1】:

    这对我很有效。而且它不会每次都重新加载捆绑包。我尝试获取一些统计信息以从外部文件位置加载和重新加载包。

    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

    【讨论】:

      【解决方案2】:

      当你说它是“一个有效的资源包”时——它是一个属性资源包吗?如果是这样,最简单的加载方法可能是:

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

      【讨论】:

      • 嗨,Jon,这难道没有错过作为首先使用捆绑软件的主要原因的本地化问题吗?
      • 没有迹象表明他实际上拥有多个文件。它有一个 .txt 后缀的事实并不是非常令人鼓舞。但是,是的,在那种情况下它会失败。
      • 与其手动加载文件(即使用FileInputStream)并构造ProperyResourceBundle,“正确的方法”不应该是使用ResourceBundle.getBundle(...)方法吗?
      • @Vihung ResourceBundle.getBundle() 将从类路径加载资源包并使用给定的语言环境。不是 OP 所期望的“原始”文件。
      【解决方案3】:

      1) 将扩展名更改为属性(例如 mybundle.properties。)
      2) 将您的文件放入 jar 中并将其添加到您的类路径中。
      3) 使用此代码访问属性:

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

      【讨论】:

      • 不幸的是,如果 jar 被 Launch4j 嵌入到可执行文件中,这是不可能的......
      • 属性文件不必在 JAR 中。如果类在包a.b.c.MyClass.java 中,那么mybundle.properties 必须在aparent 文件夹中,这将是类路径。 IE。对于 /myproject/a/b/c/MyClass.java 类,资源包必须放在 /myproject/mybundle.properties 中。
      【解决方案4】:
      ResourceBundle rb = ResourceBundle.getBundle("service"); //service.properties
      System.out.println(rb.getString("server.dns")); //server.dns=http://....
      

      【讨论】:

      • 你能提供更多关于你的答案的信息吗?
      【解决方案5】:

      对于 JSF 应用程序

      从给定文件路径获取资源包道具文件以在 JSF 应用程序中使用它们。

      • 使用 URLClassLoader 为扩展的类设置捆绑包 ResourceBundle 从文件路径加载包。
      • loadBundle 标记的basename 属性中指定类。 <f:loadBundle basename="Message" var="msg" />

      有关扩展 RB 的基本实现,请参阅Sample Customized Resource Bundle 的示例

      /* 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) 类。

      【讨论】:

        【解决方案6】:
        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);
        
            }
        }
        

        【讨论】:

          【解决方案7】:

          这对我有用:

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

          【讨论】:

          • ... 错过了 finally: 中的右括号:
          【解决方案8】:

          只要您正确命名资源包文件(使用 .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

          【讨论】:

          • 这个答案完全匹配。感谢分享。
          • 谢谢,这绝对是为插件等处理类加载器的直接路径的方法......
          • 但这也许每次都会重新加载捆绑包?
          • 注意:您可能应该关闭URLClassLoader,否则只要您的应用程序运行,文件就会被锁定。
          【解决方案9】:

          我更喜欢使用 resourceboundle 类来加载属性 - 只需一行而不是通过流、属性类和 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);
              }       
          
          }
          

          【讨论】:

            【解决方案10】:

            如果您想加载不同语言的消息文件,只需使用 shared.loader= catalina.properties 的... 欲了解更多信息,请访问http://theswarmintelligence.blogspot.com/2012/08/use-resource-bundle-messages-files-out.html

            【讨论】:

              【解决方案11】:

              如果像我一样,您确实想从文件系统而不是类路径加载 .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,我认为默认情况下不支持。

              【讨论】:

              • 对包含非 ASCII ISO-8859-1 字符(代码点 128-255)的 .properties 文件支持 UTF-8 中断,这是合法的。 ISO-8859-1 用一个字节表示它们,而 UTF-8 用两个字节表示它们。
              • 此评论不正确。 UTF-8 具有可变的字节数,是国际化的正确答案——这就是使用 ResourceBundles 的重点。请参阅此相关问题和相关的已接受答案。 stackoverflow.com/questions/10229156/…
              【解决方案12】:

              文件名应具有 .properties 扩展名,并且基目录应位于类路径中。否则它也可以在类路径中的 jar 中 相对于类路径中的目录,可以使用 / 或 指定资源包。分隔器。 “。”是首选。

              【讨论】:

                【解决方案13】:

                我认为您希望文件的位于类路径上,而不是实际文件本身。

                试试这个(可能需要一些调整):

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

                【讨论】:

                  【解决方案14】:

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

                  baseName - 的基本名称 资源包,一个完全合格的 类名

                  用简单的英语意味着资源包必须在类路径上,baseName 应该是包含包的包加上包名,在你的情况下为mybundle

                  去掉扩展名和构成包名称一部分的任何语言环境,JVM 将根据默认语言环境为您排序 - 有关更多信息,请参阅java.util.ResourceBundle 上的文档。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-03-19
                    • 1970-01-01
                    • 2023-04-06
                    • 2021-03-06
                    • 2020-08-28
                    • 1970-01-01
                    相关资源
                    最近更新 更多