除了自己实现java文本处理properties配置资源文件这个坏习惯之外,使用JDK自带类库读取Properties文件的方法主要有三种
ClassLoader.getResourceAsStream ("some/pkg/resource.properties"); Class.getResourceAsStream ("/some/pkg/resource.properties"); ResourceBundle.getBundle ("some.pkg.resource");
下面使用示例分别讲解这些方法的应用。建立一个包config,在config包下建一个文件a.properties,并在a.properties下添加如下信息:
# key = value name = kaka age = 28
建立一个包prop,在prop包下建立一个名为 PropertiesWithStream 的java类文件。由于前两种方法的实现非常类似:
package prop; import java.io.IOException; import java.io.InputStream; import java.util.Properties; // 參考 http://www.jz123.cn/text/1824271.html public class PropertiesWithStream { public static void main(String[] args) throws IOException { PropertiesWithStream propLoader = new PropertiesWithStream(); System.out.println("--- Properties from Class.getResourceAsStream ---"); // 注意,class里的getResourceAsStream()方法里参数的类路径一定要在前面加上"/",否则会报错 InputStream in = propLoader.getClass().getResourceAsStream( "/config/a.properties"); displayAllProperties(getPropertiesFromInputStream(in)); System.out.println("--- Properties from ClassLoader.getResourceAsStream ---"); // 注意,ClassLoader的getResourceAsStream()方法里参数的类路径一定不要在前面加上"/",否则会报错,是不是很奇怪。 in = propLoader.getClass().getClassLoader().getResourceAsStream( "config/a.properties"); displayAllProperties(getPropertiesFromInputStream(in)); } private static Properties getPropertiesFromInputStream(InputStream in) throws IOException { Properties prop = new Properties(); prop.load(in); return prop; } private static void displayAllProperties(Properties prop) { for (Object key : prop.keySet()) System.out.println(key + " : " + prop.getProperty(key.toString())); } }
这里将properties文件的内容读在了一个Properties类中,Properties文件时Hashtable的一个子类,用来处理配置文件的键值对。上面的示例介绍了Properties的load方法,和遍历方法,下面介绍它的另一些有用的方法:
// 获取 color 的属性值,如没有将以 green 的默认值替代 String color = prop.getProperty("color", "gray"); // 设定 color 的属性值为 red prop.setProperty("color", "red"); // 将Properties存辉一个配置文件中 prop.store(new FileOutputStream(configfilePath), "MyApp Config File");
另一种方式是使用 ResourceBundle 类来处理这类资源,其使用方法非常简单,而且还有利于本地化的实现,下面举例说明一下。
我们在 a 的相同路径下创建一个 a_en_UK.properties,其内容与a.properties一样为:
# key = value name = kaka age = 28
再创建一个 a_zh.properties,使用native2ascii命令或类似工具将“卡卡”这样的非西欧字符转换成ascii码文件格式,其内容为:
# key = value name = \u5361\u5361 age = 28
使用 ResourceBundle 只需要几行就能完成资源的绑定工作,可以看到这个资源的命名可以使用'.'或'/'分隔,效果是一样的。这里还使用了不同的Locale的不同显示效果, 其中具体的后缀名可以使用getLanguage 和 getCountry 来确定,例如Locale.UK 的 language和country分别是en 和 UK,所以Locale.UK对应的资源文件是a_en_UK.properties
package prop; import java.util.Locale; import java.util.ResourceBundle; // http://www.lifevv.com/java/doc/20080205000526940.html public class TestProperties { public static void main(String []args) { System.out.println("--- Default Locale ---"); ResourceBundle resource = ResourceBundle.getBundle("config/a"); displayResourceBundle(resource); System.out.println("--- Locale.UK ---"); resource = ResourceBundle.getBundle("config.a", Locale.UK); displayResourceBundle(resource); } private static void displayResourceBundle(ResourceBundle resource) { for (Object key : resource.keySet()) System.out.println(key + " : " + resource.getString(key.toString())); } }
当配置的使用更加复杂时,我们可能需要更多提供更多的功能,此时可以使用Apache Commons Configuration 来帮助管理我们的配置文件。Apache Commons Configuration提供了丰富的功能来处理配置工作,不好的地方是需要在工程中引入好几个jar文件才能够正常工作,具体的 Runtime Dependencies 见这里 http://commons.apache.org/configuration/dependencies.html
这里举一个简单的例子来说明Apache Commons Configuration的使用方法。首先在config包下建一个文件application.properties,并在文件中添加如下信息:
application.name = Killer App application.version = 1.6.2 application.title = ${application.name} ${application.version}
注意到这里使用了变量代换的语法,下面是一个java示例,可以看到Apache Commons Configuration不仅对property加了类型转换,还能处理队列的形式,并且能很容易做出与XML文件类型的转换
package prop; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.apache.commons.configuration.ConfigurationConverter; import org.apache.commons.configuration.ConfigurationUtils; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.XMLConfiguration; public class ApacheConfigurationTest { /** * @throws ConfigurationException * @param args * @throws */ public static void main(String[] args) throws Exception{ PropertiesConfiguration config = new PropertiesConfiguration("config/application.properties"); // Using Variable Interpolation System.out.println(config.getString("application.title")); // Get a Properties object with the Configuration Properties prop = ConfigurationConverter.getProperties(config); Iterator iterator = config.getKeys(); while(iterator.hasNext()) { String key = iterator.next().toString(); System.out.println(key + " : " + config.getProperty(key)); } config.setListDelimiter('/'); // Change the list delimiter character to a slash // Now add some properties config.addProperty("magicnumber", 42); config.addProperty("colors.pie", new String[] { "#FF0000", "#00FF00", "#0000FF" }); config.addProperty("colors.graph", "#808080/#00FFCC/#6422FF"); // Access data int magic = config.getInt("magicnumber"); ListcolPie = config.getList("colors.pie"); String firstPieColor = config.getString("colors.pie"); String[] colGraph = config.getStringArray("colors.graph"); // Notice 当文件路径中包含中文字符时可能会有乱码文件夹出现 config.save("config/app.properties"); // get the XML configuration file XMLConfiguration hc = new XMLConfiguration( ConfigurationUtils.convertToHierarchical(config)); hc.save(System.out); } }
除了对配置文件的处理,Apache Commons Configuration还能对不同的配置源进行整合处理,这里就不再介绍了,感兴趣的请参考其主页。