Properties

1. Properties类

Java中有个比较重要的类PropertiesJava.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置。像Python支持的配置文件是.ini文件,同样,它也有自己读取配置文件的类ConfigParse,方便程序员或用户通过该类的方法来修改.ini配置文件。在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”(key=value)的格式,文本注释信息可以用”#”来注释。
Properties的继承情况如下:

java.util
Class Properties

java.lang.Object
    |_java.util.Dictionary
      |_java.util.Hashtable
        |_java.util.Properties
All Implemented Interfaces:
Serializable, Cloneable, Map
Direct Known Subclasses:
Provider

Properties类提供了一个可持久化的属性集,属性集可以保存为流或从流中加载,在属性列表中每个键及其对应值是一个字符串。
由于Properties类继承自Hashtable,所以putputAll方法也可以用于Properties,不过这是强烈不推荐的做法,因为它们允许调用者插入不是String的键key和值value。应该使用setProperty 方法,如果使用了包含非StringkeyvalueProperties对象调用store 或者 save会失败,同样的使用了包含非StringkeyProperties对象调用propertyNames 或者 list也会失败。

2. Properties的主要方法

Properties类提供了操作.properties文件的一下常用方法。
- Object setProperty(String key, String value)设置属性信息
- String getProperty(String key) 获取属性信息
- void list(PrintStream out)void list(PrintWriter out) 打印属性信息
- void load(Reader reader)void load(InputStream inStream) 加载.properties文件(默认的编码是ISO 8859-1,不能直接表示的字符可以使用Unicode转义)
- void loadFromXML(InputStream in)从XML文档中加载.properties文件(默认是UTF-8编码,如果有需要可以指定其它编码方式,XML文档要有声明)
- void store(Writer writer, String comments)void store(OutputStream out, String comments)存储.properties文件(默认的编码是ISO 8859-1,不能直接表示的字符可以使用Unicode转义)
- void storeToXML(OutputStream os, String comment)
void storeToXML(OutputStream os, String comment, String encoding)存储.properties文件为XML文档(默认是UTF-8编码,如果有需要可以指定其它编码方式,XML文档要有声明)
- Enumeration propertyNames()Set stringPropertyNames()返回.properties文件中的keys

3. Properties文件

# 正常的key-value对
IDEASystem=Windows7
IDEAName=weegee
# 没有=的key-value对,仍然是正确的,只要中间有间隔就会被正确解析
IDEAUpdate FALSE
# 只有key没有等号,则认为value=""
IDEAPassword
# 有=没有value,同上
IDEAPassword!!!=
# 没有key,则被认为key=""
=null
# 没有key和value,认为key="",value=“”
=
# 正常的key-value对,使用了断行符\
IDEAVersion=\
  15.0.6

因为Properties类继承自HashTable,则不能有相同的key,若是存在相同的key-value,则只会存储第一个被加载的key-value对。

4. Properties文件操作

4.1 load方法加载.properties文件

在读取文件之前,先看一下我的目录结构,这个设置文件路径时候很重要。

src
|-com
| |-weegee
| | |-properties
| | | |-java类
| new.properties
| ...(各种.properties文件或者.xml文件)

在加载文件的时候,”/”代表了工程的根目录,例如工程名叫做myproject,”/”代表了myproject,没有”/”时则代表项目内的路径信息。
目前常见的有6种加载Properties文件的方法:
1. 使用java.util.Properties类的load()方法

/**
     * 使用java.util.Properties类的load()方法,FileInputStream的参数可以直接写文件的相对路径
     */
    public static void loadProperties() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream("src/new.properties"));
            properties.load(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                System.out.println(key + " = " + value);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.使用java.util.ResourceBundle类的getBundle()方法

/**
     * ResourceBundle在读取properties文件时统一使用iso8859-1编码
     * 因此,如果在默认编码为 GBK的系统中编写了包含中文的properties文件
     * 经由ResourceBundle读入时,必须转换为GBK格式的编码,否则不能正确识别
     *
     * ResourceBundle.getBundle(String baseName, Locale locale);
     * 第一个参数是为资源文件的名字,注意不用写后缀名且不能含有路径信息
     * 第二个参数使用Locale设置国家和地区支持国际化
     * 可以自己设定Locale locale = new Locale("en", "GB");
     * 第一个参数是语言代码,第二个参数是国家代码
     * 也可以使用java.util.Locale的Locale.getDefault()获取本地语言环境
     */
    public static void GetBundle() {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("new", Locale.getDefault());
        Iterator iterator = resourceBundle.keySet().iterator();
        while(iterator.hasNext()) {
            String key = iterator.next();
            String value = resourceBundle.getString(key);
            System.out.println(key + " = " + value);
        }
    }

3.使用java.util.PropertyResourceBundle类的构造函数

/**
     * 使用java.util.PropertyResourceBundle类的构造函数
     * FileInputStream的参数可以直接写文件的相对路径
     */
    public static void PropertyResourceBundle() {
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream("src/new.properties"));
            ResourceBundle resourceBundle = new PropertyResourceBundle(inputStream);
            Iterator iterator = resourceBundle.keySet().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = resourceBundle.getString(key);
                System.out.println(key + " = " + value);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.使用class变量的getResourceAsStream()方法
Class.getResourceAsStream(String path)读取的文件路径只局限与工程的源文件夹中,包括在工程src根目录下,以及类包里面任何位置,但是如果配置文件路径是在除了源文件夹之外的其他文件夹中时,该方法是用不了的。
Class.getResourceAsStream(String path) 加载文件时有以下几种:
- 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类me.class ,同时有资源文件myfile.xml

me.class.getResourceAsStream("myfile.xml"); 
  • 在me.class目录的子目录下,例如:com.x.y 下有类me.class ,同时在 com.x.y.file 目录下有资源文件myfile.xml
me.class.getResourceAsStream("file/myfile.xml"); 
  • 不在me.class目录下,也不在子目录下,例如:com.x.y 下有类me.class ,同时在 com.x.file 目录下有资源文件myfile.xml
me.class.getResourceAsStream("/com/x/file/myfile.xml"); 
/**
     * 使用class变量的getResourceAsStream()方法
     *  Class.getResourceAsStream(String path)
     *  path 不以’/'开头时默认是从此类所在的包下取资源
     *  以’/'开头则是从ClassPath根下获取
     *  其只是通过path构造一个绝对路径,最终还是由 ClassLoader获取资源
     */
    public static void GetResourceAsStream() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = PropertiesTest.class.getResourceAsStream("/new.properties");
            properties.load(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                System.out.println(key + " = " + value);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5.使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法

/**
     * 使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法
     * Class.getClassLoader.getResourceAsStream(String path)
     * 默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源
     */
    public static void GetClassLoader() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = PropertiesTest.class.getClassLoader().getResourceAsStream("new.properties");
            properties.load(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                System.out.println(key + " = " + value);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6.使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法

/**
     * 使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法
     * ClassLoader.getSystemResourceAsStream(String path)
     * 默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源
     */
    public static void ClassLoader() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = ClassLoader.getSystemResourceAsStream("new.properties");
            properties.load(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                System.out.println(key + " = " + value);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

**注:**Servlet中可以使用javax.servlet.ServletContext的getResourceAsStream()方法,ServletContext. getResourceAsStream(String path):默认从Webapp根目录下取资源,Tomcat下path是否以’/’开头无所谓,和具体的容器实现有关。

Properties properties = new Properties();
InputStream inputStream= context.getResourceAsStream(path);
properties.load(inputStream);

4.2 新建和写入.properties文件

新建.properties文件

/**
     * 创建.properties文件
     */
    public static void CreateProperties() {
        //写入key和value的值
        Properties properties = new Properties();
        properties.setProperty("IDEASystem","Windows7");
        properties.setProperty("IDEAName","weegee");
        properties.setProperty("IDEAVersion","15.0.1");
        //写入时key和value的值不能为null
        //properties.setProperty("IDEAPassword",null);
        //properties.setProperty(null,"null");
        properties.setProperty("IDEAUpdate","");
        //可以这样写,设置为空
        properties.setProperty("","");
        properties.setProperty("","TRUE");

        try {
            PrintStream printStream = new PrintStream(new File("src/old.properties"));
            PrintStream printStream1 = new PrintStream(new File("src/old1.properties"));
            //list方法保存
            properties.list(printStream);
            //store方法保存,第二个参数是注释信息
            properties.store(printStream1,"store");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

写入的文件信息如下:
old.properties

-- listing properties --
IDEASystem=Windows7
IDEAName=weegee
IDEAUpdate=
IDEAVersion=15.0.1
=TRUE

old1.properties

#store
#Sun Oct 09 20:42:49 CST 2016
IDEASystem=Windows7
IDEAName=weegee
IDEAUpdate=
IDEAVersion=15.0.1
=TRUE

写入.properties文件

/**
     * 写入Properties信息
     * @param 写入文件的路径
     * @param 写入的键
     * @param 写入的值
     */
    public static void WriteProperties (String filePath, String pKey, String pValue) {
        Properties properties = new Properties();
        try {
            InputStream inputStream = new FileInputStream(filePath);
            //从输入流中读取属性列表(键和元素对)
            properties.load(inputStream);
            //调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
            //强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
            OutputStream out = new FileOutputStream(filePath);
            properties.setProperty(pKey, pValue);
            //以适合使用 load 方法加载到 Properties 表中的格式,
            //将此 Properties 表中的属性列表(键和元素对)写入输出流
            //第二个参数是说明信息
            properties.store(out, "Update:new property  " + pKey );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.3 修改.properties文件的属性值对

/**
     * 修改属性的值,把value=15.0.1的IDEAVersion的值改为15.0.6
     */
    public static void ModifyValue() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream("src/new.properties"));
            properties.load(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                if("15.0.1".equals(value)){
                    properties.setProperty(key,"15.0.6");
                }
            }
            properties.store(new FileOutputStream("src/new.properties"),"modify version");
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.4 删除.properties文件的某个属性

/**
     * 删除信息,由于不能在properties文件中直接删除信息
     * 所以需要把信息读取到一个map中,然后删除map中相应的信息
     * 再把map的信息读入到properties中,再写到文件中
     */
    public static void DeleteProperty() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream("src/new.properties"));
            properties.load(inputStream);
            //新建map用来存放properties文件的信息
            Map map = new HashMap();
            Set keySet = properties.keySet();
            //遍历properties的key,然后获取value,存放到map
            for(Iterator iterator = keySet.iterator(); iterator.hasNext();) {
                String key = (String) iterator.next();
                String value = (String) properties.get(key);
                map.put(key,value);
            }
            //删除properties的所有信息
            properties.clear();
            //从map中移除要删除的属性
            map.remove("IDEAError");
            //把map的信息存放到properties
            properties.putAll(map);
            properties.store(new FileOutputStream("src/new.properties"),"delete error");
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    } 
  

这里删除属性借用了map,其实在修改或者写入属性的时候也可以借助于map。先properties.load把原文件信息读入到properties,然后把properties的信息存放到map中,再清除properties,接着直接在map上进行修改和增加,然后在把map保存早properties,在写入到原文件。

4.5 loadFromXML读取XML文件

.xml格式的.properties文件



<properties>
<comment>modify versioncomment>
<entry key="IDEASystem">Windows7entry>
<entry key="IDEAName">weegeeentry>
<entry key="IDEAVersion">15.0.1entry>
<entry key="IDEAPassword">nullentry>
properties>

comment那行代表的是说明信息,相当于.properties的注释说明,entry 行是键值对。

/**
     * 使用loadFromXML从XML文件中获取
     * FileInputStream的参数可以直接写文件的相对路径
     */
    public static void LoadFromXML() {
        Properties properties = new Properties();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream("src/new.xml"));
            properties.loadFromXML(inputStream);
            Iterator iterator = properties.stringPropertyNames().iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                String value = properties.getProperty(key);
                System.out.println(key + " = " + value);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.6 storeToXML存为XML文件

/**
     * 保存为XML文件
     */
    public static void StoreToXML() {
        Properties properties = new Properties();
        properties.setProperty("IDEASystem","Windows7");
        properties.setProperty("IDEAName","weegee");
        properties.setProperty("IDEAVersion","15.0.1");
        //properties.setProperty("IDEAPassword",null);
        //properties.setProperty(null,"null");
        properties.setProperty("IDEAUpdate","");
        properties.setProperty("","");
        properties.setProperty("","TRUE");

        try {
            PrintStream printStream = new PrintStream(new File("src/old.xml"));
            //第二个参数是说明信息,第三个参数是编码格式
            properties.storeToXML(printStream,"storeXML","UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

虽然只.xml文件,旦和.properties文件相比仅仅实在读取和存储的时候使用的函数不一样,适用于.properties文件的增、删、改属性同样适用于.xml文件。

你可能感兴趣的:(Java,JavaWeb)