Java中Properties类

来源:互联网 发布:虎鲸vs大白鲨 知乎 编辑:程序博客网 时间:2024/06/05 20:29

1 简介:

  JDK提供的java.util.Properties类继承自Hashtable类并且实现了Map接口,用map来存储key-value数据,所以存入的数据是无序的。其中键和值都是字符串类型。

2 java.util.Properties类

  在Java中,其配置文件常为.properties文件,格式为文本文件,内容的格式为“键=值”的格式,#打头的是注释行,Properties会忽略注释。允许只有key没有value,没有value时,value会被set成null。java.util.Properties是对properties这类配置文件的映射。支持key-value类型和xml类型两种。java.util.Properties类提供了几个很重要的方法,归纳如下:

  1) getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value值

  2)setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。

  3)load( InputStream inStream),从输入流中读取属性列表(键值对)。通过对指定的文件进行装载来获取该文件中的所有键 - 值对以供 getProperty ( String key) 来搜索。load有两个方法的重载:load(InputStream inStream)、load(Reader reader),可根据不同的方式来加载属性文件。

InputStream inStream = TestProperties.class.getClassLoader().getResourceAsStream("demo.properties");  //通过当前类加载器的getResourceAsStream方法获取//TestProperties当前类名;TestProperties.class.取得当前对象所属的Class对象; getClassLoader():取得该Class对象的类装载器InputStream in = ClassLoader.getSystemResourceAsStream("filePath");InputStream in = new BufferedInputStream(new FileInputStream(filepath));InputStream inStream = new FileInputStream(new File("filePath"));  //从文件获取InputStream in = context.getResourceAsStream("filePath");          //在servlet中,可以通过context来获取InputStreamInputStream inStream = new URL("path").openStream();             //通过URL来获取

读取方法如下:

Properties pro = new Properties();                       //实例化一个Properties对象InputStream inStream = new FileInputStream("demo.properties");       //获取属性文件的文件输入流pro.load(nStream);inStream.close();
  4)store( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。
FileOutputStream outStream = new FileOutputStream("demo.properties");pro.store(outStream,"Comment");outStream.close();

  5)clear (),清除所有装载的 键 - 值对。该方法在基类中提供。

   java.util.ResourceBundle类也提供了读取Properties配置文件的方法,ResourceBundle是一个抽象类。

  附:ResourceBundle中的主要方法: 通过ResourceBundle.getBundle()静态方法来获取,此方法获取properties属性文件不需要加.properties后缀名。也可以从InputStream中获取ResourceBundle对象。在使用中遇到的问题可能是配置文件的路径,当配置文件不在当前类所在的包下,则需要使用包名限定;若属性文件在src根目录下,则直接使用demo.properties或demo即可。

ResourceBundle resource = ResourceBundle.getBundle("com/xiang/demo");//emo为属性文件名,放在包com.xiang下,如果是放在src下,直接用test即可  ResourceBundle resource1 = new PropertyResourceBundle(inStream);   String value = resource.getString("name"); 

3 Properties实例

  1)Java虚拟机(JVM)有自己的配置文件(system.properties),如下就可以获得JVM的系统属性

import java.util.Properties;public class ReadJVM {     public static void main(String[] args) {          Properties pps = System.getProperties();          pps.list(System.out);      }}
  2)新建一个配置文件Test.properties
name=JJWeight=4444Height=3333 
  public class getProperties {      public static void main(String[] args) throws FileNotFoundException, IOException {          Properties pps = new Properties();          pps.load(new FileInputStream("Test.properties"));       //第一步就是要将文件读取到Properties类对象中,由于load有一个参数是InputStream,所以我们可以用 InputStream的子类FileInputStream将属性文件读取到
//Properties对象中,知道prop.properties的路径,我们就用FileInputStream(String name)构造函数:          Enumeration enum1 = pps.propertyNames();//得到配置文件的名字          while(enum1.hasMoreElements()) {              String strKey = (String) enum1.nextElement();              String strValue = pps.getProperty(strKey);             System.out.println(strKey + "=" + strValue);         }     }}
如下类实现了Properties的常用操作
//关于Properties类常用的操作public class TestProperties {    //根据Key读取Value    public static String GetValueByKey(String filePath, String key) {        Properties pps = new Properties();        try {            InputStream in = new BufferedInputStream (new FileInputStream(filePath));              pps.load(in);            String value = pps.getProperty(key);            System.out.println(key + " = " + value);            return value;                    }catch (IOException e) {            e.printStackTrace();            return null;        }    }        //读取Properties的全部信息    public static void GetAllProperties(String filePath) throws IOException {        Properties pps = new Properties();        InputStream in = new BufferedInputStream(new FileInputStream(filePath));        pps.load(in);        Enumeration en = pps.propertyNames(); //得到配置文件的名字                while(en.hasMoreElements()) {            String strKey = (String) en.nextElement();            String strValue = pps.getProperty(strKey);            System.out.println(strKey + "=" + strValue);        }            }        //写入Properties信息    public static void WriteProperties (String filePath, String pKey, String pValue) throws IOException {        Properties pps = new Properties();                InputStream in = new FileInputStream(filePath);        //从输入流中读取属性列表(键和元素对)         pps.load(in);        //调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。          //强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。        OutputStream out = new FileOutputStream(filePath);        pps.setProperty(pKey, pValue);        //以适合使用 load 方法加载到 Properties 表中的格式,          //将此 Properties 表中的属性列表(键和元素对)写入输出流          pps.store(out, "Update " + pKey + " name");    }        public static void main(String [] args) throws IOException{        //String value = GetValueByKey("Test.properties", "name");        //System.out.println(value);        //GetAllProperties("Test.properties");        WriteProperties("Test.properties","long", "212");    }}

结果:Test.properties中文件的数据为 

#Update long name
#Sun Feb 23 18:17:16 CST 2014
name=JJ
Weight=4444
long=212
Height=3333

   除此之外,java的properties文件需要放到classpath下面,这样程序才能读取到,有关classpath实际上就是java类或者库的存放路径,在java工程中,properties放到class文件一块。在web应用中,最简单的方法是放到web应用的WEB- INF\classes目录下即可,也可以放在其他文件夹下面,这时候需要在设置classpath环境变量的时候,将这个文件夹路径加到 classpath变量中,这样也也可以读取到。在此,你需要对classpath有个深刻理解,classpath绝非系统中刻意设定的那个系统环境变量,WEB-INF\classes其实也是,va工程的class文件目录也是。

  在我们知道如何读写一个属性文件之后,我们仍然还有很多需要注意的问题,因为load和store方法都是按照ISO-8859-1的编码方式读写属性流文件的,而ILatin1 的字符和某些特殊字符,而对于非Latin1 的字符和某些特殊字符,则要使用与字符和字符串字面值所用的类似转义序列,以值和元素的形式来表示它们。所以当我们在处理中文时,不可以在直接修改属性文件时,将中文的值赋予给属性,而是要在JAVA程序中通过setProperty方法给属性赋予中文的值,因为这样store会将中文转换成 unicode码,在读取时系统会将读取到的unicode码按系统的编码打印出来,对于中文系统,通常是GBK码,这样中文才能够正常显示。

   3)Java中Properties配置文件工具类

import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Properties;/** * Java中Properties配置文件工具类 * @author shu * */public class PropsUtil {    private String path = "";    private Properties properties ;        /**     * 默认构造函数     */    public PropsUtil() {}        /**     * 构造函数     * @param path 传入Properties地址值     */    public PropsUtil(String path) {        this.path = path;    }        /**     * 加载properties文件     * @return 返回读取到的properties对象     */    public Properties loadProps(){        InputStream inStream  = ClassLoader.getSystemResourceAsStream(path);                try {            if(inStream==null)                throw new FileNotFoundException(path + " file is not found");            properties = new Properties();            properties.load(inStream);            inStream.close();        } catch (IOException e) {            e.printStackTrace();        }        return properties;    }        /**     * 将配置写入到文件     */    public void writeFile(){        // 获取文件输出流        try {            FileOutputStream outputStream = new FileOutputStream( new File(ClassLoader.getSystemResource(path).toURI()));            properties.store(outputStream, null);            outputStream.close();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }        /**     * 通过关键字获取值     * @param key     * @return 返回对应的字符串,如果无,返回null     */    public String getValueByKey(String key) {        if(properties==null)            properties = loadProps();        String val = properties.getProperty(key.trim());        return val;    }        /**     * 通过关键字获取值     * @param key 需要获取的关键字     * @param defaultValue 若找不到对应的关键字时返回的值     * @return  返回找到的字符串     */    public String getValueByKey(String key,String defaultValue){        if(properties==null)            properties = loadProps();        return properties.getProperty(key, defaultValue);    }        /**     * 获取Properties所有的值     * @return  返回Properties的键值对     */    public Map<String, String> getAllProperties() {        if(properties==null)            properties = loadProps();        Map<String, String> map = new HashMap<String, String>();        // 获取所有的键值        Iterator<String> it=properties.stringPropertyNames().iterator();        while(it.hasNext()){            String key=it.next();           map.put(key, properties.getProperty(key));        }        /*Enumeration enumeration = properties.propertyNames();        while (enumeration.hasMoreElements()) {            String key = (String) enumeration.nextElement();            String value = getValueByKey(key);            map.put(key, value);        }*/        return map;    }    /**     * 往Properties写入新的键值且保存     * @param key 对应的键     * @param value 对应的值     */    public void addProperties(String key, String value) {        if(properties==null)            properties = loadProps();        properties.setProperty(key, value);        try {            writeFile();        } catch (Exception e) {            throw new RuntimeException("write fail");        }    }        /**     * 更新配置文件     * @param key 对应的键     * @param value 对应的值     */     public void update(String key,String value){         if(properties==null)            properties = loadProps();         if(properties.containsKey(key))             properties.replace(key, value);        try {            writeFile();        } catch (Exception e) {            throw new RuntimeException("write fail");        }     }          /**      * 刪除某一鍵值对      * @param key      */     public void deleteByKey(String key){         if(properties==null)            properties = loadProps();         if(!properties.containsKey(key))             throw new RuntimeException("not such key");         properties.remove(key);         try {            writeFile();         } catch (Exception e) {            throw new RuntimeException("write fail");        }     }          /**      * 设置path值      * @param path      */     public void setPath(String path){         this.path = path;     }}

4 XML配置形式文件操作

xml形式的配置文件格式大略是这样:

<?xml version="1.0" encoding="UTF-8"?>  <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  <properties>  <comment>Hi</comment>  <entry key="foo">bar</entry>  <entry key="fu">baz</entry>  </properties>  
读取xml配置跟读取kv配置没差别,就是把load换成xml对应的loadFromXML方法,代码大略是这样:
  public class LoadSampleXML {        public static void main(String args[]) throws Exception {          Properties prop = new Properties();          FileInputStream fis =            new FileInputStream("sampleprops.xml");          prop.loadFromXML(fis);          prop.list(System.out);          System.out.println("\nThe foo property: " +              prop.getProperty("foo"));       }   }  
把内存中的properties对象写入到xml文件中也和上面差不多,就是把list方法改成xml对应的storeToXML方法。代码大略是这样:
  import java.io.IOException;  import java.io.File;  import java.io.FileInputStream;  import java.io.PrintStream;  import java.util.Properties;    public class Test {      public static void main(String[] args) {          Properties p = new Properties();         p.setProperty("id","dean");         p.setProperty("password","123456");          try{             PrintStream fW = new PrintStream(new File("e:\\test1.xml"));             p.storeToXML(fW,"test");         } catch (IOException e) {             e.printStackTrace();         }     } }          

1 0