java IO流之属性集Properties【八】
1.概述
java.util.Properties
继承于 Hashtable
,用来表示一个持久的属性集合。
Properties
集合是唯一一个和IO流相结合的集合,可以保存在IO流中,也可以从IO流中加载。
- 使用
store()
方法,可以把集合中的临时数据,持久化存储到硬盘中。 - 使用
load()
方法,可以把硬盘中的文件,读取到集合中使用。
Properties
集合是一个双列集合,使用键值结构存储数据,key和value默认都是字符串,且Key唯一。
该类被许多Java类使用,比如获取系统属性。
System.getProperties()
方法就是返回一个Properties对象。
2.构造方法:
public Properties() : 创建一个无默认值的空属性集列表。该方法等同于 Properties(null)
public Properties(Properties defaults) : 创建一个带有指定默认值的空属性列表。
2.1构造方法源码:
// 默认属性集
protected Properties defaults;
public Properties() {
this(null);
}
public Properties(Properties defaults) {
this.defaults = defaults;
}
3.存储和获取方法:
public Object setProperty(String key, String value) : 保存一对属性,底层调用 Hashtable 的 put方法 。
public String getProperty(String key) :根据key获取value。
public String getProperty(String key, String defaultValue)。根据key获取value,如果没找到,就返回defaultValue。
public Enumeration<?> propertyNames() :返回属性列表中所有键的枚举,如果在主属性列表中未找到同名的键,则包括默认属性列表中不同的键。
public Set<String> stringPropertyNames() :返回此属性列表中的键集。如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
3.1存储和获取方法的源码:
// 保存属性,底层调用hashtable的put方法,该方法是线程安全的。
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
// 根据key获取value
public String getProperty(String key) {
// 调用hashtable的get方法。
Object oval = super.get(key);
// 判断oval 是否是String,如果是,就返回,如果不是,就是null
String sval = (oval instanceof String) ? (String)oval : null;
/**
* 1.如果sval不为null,返回sval
* 2.如果sval为null, 默认属性集存在,就去默认属性集中获取value。
* 3.如果sval为null, 默认属性集不存在,返回null。
*/
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
// 根据key获取value
public String getProperty(String key, String defaultValue) {
String val = getProperty(key);
// 如果没有获取到value,就返回defaultValue
return (val == null) ? defaultValue : val;
}
// 获取属性集中所有key,将其存入set集合中,并返回
public Set<String> stringPropertyNames() {
Hashtable<String, String> h = new Hashtable<>();
//将属性集的key和value列举,并存入hashtable中
enumerateStringProperties(h);
// 获取hashtable中所有key的set集合
return h.keySet();
}
// 枚举方法
private synchronized void enumerateStringProperties(Hashtable<String, String> h) {
if (defaults != null) {
// 如果默认属性集存在,也进行遍历
defaults.enumerateStringProperties(h);
}
//获取属性集中key的枚举,并进行遍历。
for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
Object k = e.nextElement();
// 根据key获取value
Object v = get(k);
if (k instanceof String && v instanceof String) {
// 如果key和value都是字符串,把它们都存入hashtable中。
h.put((String) k, (String) v);
}
}
}
//和上面的方法类似,区别是它返回key的枚举,而上面的放回返回key的set集合
public Enumeration<?> propertyNames() {
Hashtable<String,Object> h = new Hashtable<>();
enumerate(h);
return h.keys();
}
// 枚举方法
private synchronized void enumerate(Hashtable<String,Object> h) {
if (defaults != null) {
// 如果默认属性集存在,也进行遍历
defaults.enumerate(h);
}
for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
String key = (String)e.nextElement();
h.put(key, get(key));
}
}
3.2简单演示
package com.hanyxx.io;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
/**
* @author layman
*/
public class Demo01 {
private static Properties p = new Properties();
static{
// 设置key和value
p.setProperty("name1","outerMan");
p.setProperty("name2","layman");
}
public static void main(String[] args) {
//test01();
test02();
}
// 构造带有默认属性集的Properties
private static void test02() {
Properties p1 = new Properties(p);
p1.setProperty("name1","Lily");
p1.setProperty("name3","刘大脑袋");
p1.setProperty("name4","Rose");
// p1中的name1和p中重复了。
System.out.println(p1.getProperty("name1"));
// 获取属性集中key的set集合
Set<String> set = p1.stringPropertyNames();
System.out.println(set);
// 获取属性集中key的枚举集
Enumeration<?> enums = p1.propertyNames();
while (enums.hasMoreElements()) {
System.out.print(enums.nextElement() + " ");
}
}
// 构造空Properties
private static void test01() {
// 根据存在的key获取value
System.out.println(p.getProperty("name1"));
// 根据不存在的key获取value
System.out.println(p.getProperty("long"));
// 根据key获取value,如果没有,返回默认值
System.out.println(p.getProperty("long", "18cm"));
System.out.println(p);
}
}
运行结果:
test01():outerMan
null
18cm
{name2=layman, name1=outerMan}
test02():Lily
[name4, name3, name2, name1]
name4 name3 name2 name1
4.持久化和读取方法:
public void store(OutputStream out,String comments):将属性集合中的键值对以字节流形式写出,comments是注释信息。
public void store(Writer writer, String comments):将属性集合中的键值对以字符流形式写出,comments是注释信息。
public void load(InputStream inStream):从字节输入流中读取属性列表(键和元素对)。
public void load(Reader reader): 从字符输入流中读取属性列表(键和元素对)。
4.1 简单演示
package com.hanyxx.io;
import java.io.*;
import java.util.Properties;
/**
* @author layman
*/
public class Demo01 {
private static Properties p = new Properties();
private static FileOutputStream fos;
private static FileWriter fw;
private static FileInputStream fis;
private static FileReader fr;
static{
// 设置key和value
p.setProperty("name1","outerMan");
p.setProperty("name2","layman");
p.setProperty("name3","钢铁侠");
p.setProperty("name4","葫芦娃");
}
public static void main(String[] args) throws IOException {
//saveFromOutputStream();
//saveFromWriter();
readFromInputStream();
//readFromReader();
}
// 以字节流形式存储,中文会显示乱码
private static void saveFromOutputStream() throws IOException {
fos = new FileOutputStream("pro_字节.txt");
String comments = "Form OutputStream";
p.store(fos,comments);
fos.close();
}
// 以字符流形式存储
private static void saveFromWriter() throws IOException {
fw = new FileWriter("pro_字符.txt");
// 注释信息使用的是unicode编码,所以使用中文注释会出现乱码
String comments = "通过字符流存储";
p.store(fw,comments);
fw.close();
}
// 以字节流形式读取,中文会显示乱码
private static void readFromInputStream() throws IOException {
fis = new FileInputStream("pro_字节.txt");
p.load(fis);
fis.close();
System.out.println(p);
}
// 以字符流形式读取
private static void readFromReader() throws IOException {
fr = new FileReader("pro_字符.txt");
p.load(fr);
fr.close();
System.out.println(p);
}
}