2009-07-23 20 views
45

tengo un archivo llamado mybundle.txt en c:/temp -¿Cómo cargar un paquete de recursos desde un recurso de archivo en Java?

c:/temp/mybundle.txt

¿Cómo se carga este archivo en un java.util.ResourceBundle? El archivo es un paquete de recursos válido.

no parece que esto funcione:

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

Respuesta

40

Cuando dicen que es "un paquete de recursos válida" - se trata de un paquete de recursos de propiedad? Si es así, la forma más sencilla de cargar probablemente:

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

Hola Jon, ¿no le falta esto al problema de localización que sería la razón principal para usar un paquete en primer lugar? –

+2

No hay indicación de que realmente haya obtenido más de un archivo. El hecho de que tenga un sufijo .txt no es muy alentador. Pero sí, fallaría en esa situación. –

+8

En lugar de cargar un archivo manualmente (es decir, con 'FileInputStream') y construir un' ProperyResourceBundle', ¿no debería ser la "forma correcta" utilizar el método 'ResourceBundle.getBundle (...)'? – Vihung

11

De los JavaDocs para ResourceBundle.getBundle(String baseName):

baseName - el nombre base del paquete recursos, un nombre completo de clase

Lo que esto significa en inglés simple es que el paquete de recursos debe estar en el classpath y que baseName debe ser el paquete que contiene el bund le más el nombre del paquete, mybundle en su caso.

Deje de utilizar la extensión y cualquier configuración regional que forme parte del nombre del paquete, la JVM lo ordenará de acuerdo con la configuración regional predeterminada; consulte los documentos en java.util.ResourceBundle para obtener más información.

0

Creo que desea que padre esté en el classpath, no en el archivo en sí.

Prueba esto (puede ser necesario algún ajuste):..

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

1) cambiar la extensión de propiedades (ex mybundle.properties)
2) Poner el archivo en un frasco y añadirlo a su classpath.
3) Acceder a las propiedades utilizando este código:

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

Desafortunadamente, esto no es posible si el archivo jar está incrustado en un archivo ejecutable por Launch4j y tal ... – Matthieu

+1

El archivo de propiedad no tiene que estar dentro de un JAR. Si la clase está en un paquete 'a.b.c.MyClass.java', entonces' mybundle.properties' tiene que estar en la carpeta * parent * de 'a', que sería el classpath. Es decir para una clase '/ myproject/a/b/c/MyClass.java' el paquete de recursos debe colocarse en'/myproject/mybundle.properties'. – ccpizza

0

El nombre del archivo debe tener la extensión .properties y el directorio de base debe estar en la ruta de clase. De lo contrario, también puede estar en un jar que está en classpath En relación con el directorio en classpath, el paquete de recursos se puede especificar con/o. separador. "." se prefiere.

2

Si, como yo, que realmente quería cargar .properties archivos de su sistema de archivos en lugar de la ruta de clases, pero por lo demás mantener todos la inteligencia relacionados con las operaciones de búsqueda, a continuación, haga lo siguiente:

  1. crear una subclase de java.util.ResourceBundle.Control
  2. anular el método newBundle()

en este tonto ejemplo, suponga que tiene una carpeta en C:\temp que contiene una lista plana de".propiedades" archivos:

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

}

Tenga en cuenta también que este es compatible con UTF-8, que creo que no está soportada por defecto de otro modo

+0

Admite saltos UTF-8 para archivos .properties que contienen caracteres que no son ASCII ISO-8859-1 (puntos de código 128-255), lo que es legal. ISO-8859-1 los representa con un byte cada uno, mientras que UTF-8 usa dos bytes para ellos. –

+0

Este comentario es incorrecto. UTF-8 tiene una cantidad variable de bytes y es la respuesta correcta para la internacionalización, que es el punto de usar ResourceBundles. Vea esta pregunta relacionada y la respuesta aceptada asociada. http://stackoverflow.com/questions/10229156/how-many-characters-can-utf-8-encode –

2

yo preferiría utilizar la clase resourceboundle a cargar. las propiedades - sólo para lograr que se haga en una sola línea de código en lugar de 5 líneas de flujo a través, clase propiedades y carga()

FYI ....

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

} 
.
5

Para la aplicación JSF

Para obtener archivos de recursos de paquetes de recursos de una ruta de archivo determinada para usarlos en una aplicación JSF.

  • Establecer el paquete con URLClassLoader para una clase que se extiende ResourceBundle para cargar el paquete de la ruta del archivo.
  • Especifique la clase en basename propiedad de la etiqueta loadBundle. <f:loadBundle basename="Message" var="msg" />

Para la implementación básica de RB extendido Por favor ver la muestra a 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) { } 
     } 
     . 
     . 
     . 
    } 

De otro modo, obtener el paquete de método getBundle pero la configuración regional de la fuente otros como Locale.getDefault(), la nueva clase (RB) puede no requiere en este caso.

53

Mientras el nombre de su paquete de recursos archivos correctamente (con la extensión .properties), entonces funciona:

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

donde "c: \ temp" es la carpeta externa (no en la ruta de clase) que contiene los archivos de propiedad, y "myresource" se refiere a myresource .properties, myResource_fr_FR.properties, e . Tc

crédito a http://www.coderanch.com/t/432762/java/java/absolute-path-bundle-file

+0

Esta respuesta coincide exactamente. Gracias por compartir. – jmcollin92

+0

Gracias, esta es definitivamente la manera de manejar una ruta directa al cargador de clases para complementos, etc ... –

+0

¿Pero quizás esto vuelva a cargar el paquete cada vez? – Seby

0

Esto funciona para mí:

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

... perdió el corchete de cierre en el final: – sius

+0

agrega el bracket que falta – sius

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

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

¿Puede proporcionar más información acerca de su respuesta? – JAL

1

He acaba de lanzar una biblioteca denominada Rincl que tiene toda la monotonía de la carga de archivos de recursos . Los archivos de recursos nombrados después de las clases se encuentran automáticamente (usando la resolución local normal). Aún mejor, los recursos para las clases principales y las interfaces se encuentran automáticamente. Además, tiene todo tipo de beneficios, como el manejo de archivos de propiedades UTF-8 y archivos de propiedades XML de forma transparente.

También puede leer un intro o un completo lesson to internationalization usando Rincl.

Cuestiones relacionadas