属性映射
属性映射(property map)是一种存储键/值对的数据结构。属性映射通常用来存储配置信息,它有3个特性:
- 键和值是字符串。
- 映射可以很容易地存入文件以及从文件加载。
- 有一个二级表保存默认值。
在 Java 中使用 Properties 来实现属性映射:
Properties settings = new Properties();
settings.setProperty("width", "200");
settings.setProperty("title", "Hello world");
当然,可以使用 store()
将属性映射列表保存到一个文件中:
OutputStream out = new FileOutputStream("program.properties");
settings.store(out, "Program Properties");
该文件会在项目主目录下创建一个名为 program.properties
的文件,文件内容为:
#Program Properties
#Tue Sep 01 11:23:07 CST 2020
width=200
title=Hello world
当然也可以使用 load()
来加载文件:
InputStream in = new FileInputStream("program.properties");
settings.load(in);
可以使用 System.getProperties()
来调用系统信息,比如使用 user.home
来调用用户主目录:
String userDir = System.getProperties(); // like get /home/yikang
如果想拿到某个属性,就可以使用 getProperty()
来获取数据:
settings.getProperty("title");
settings.getProperty("title", "Defalut title"); // 设置默认值
当然,如果觉得设置默认值麻烦,可以把所有默认值都放在一个二级属性映射中,并在主属性映射的构造器中提供这个给二级映射:
Properties defalutSettign = new Properties(); // 二级属性映射
defalutSettign.setProperty("width", "300");
defalutSettign.setProperty("height", "200");
defalutSettign.setProperty("title", "Default title");
Properties settings = new Properties(defalutSettign); // 主属性映射
这样通过提供一个属性映射来达到提供默认值的目的,甚至可以为 默认值指定默认值。当然,一般没人会这么做。
出于历史原因,Properties 是一个遗留类,它实现了
Map<Object, Object>
。因此它可以使用Map
的 get 和 put 方法。不过,get 方法会返回类型 Object,而put方法允许插入任何对象。最好坚持使用 getProperty 和 setProperty 方法,这些方法会处理字符串,而不是对象。
首选项 API
Properties 虽然很容易地加载和保存配置信息。不过,还是有一下缺点:
- 有些操作系统没有主目录的概念,所以很难找到一个统一的配置文件位置。
- 关于配置文件的命名没有标准约定,用户安装多个Java应用时,就更容易发生命名冲突。
Perferences 以一种平台无关的方式提供了这样一个中心存储库。Preferences 存储库有一个树状结构,节点路径名类似于/com/mycompany/myapp。类似于包名,可以有效的避免命名冲突。
存储库里也是用键/值进行储存。可以用来存储数值、字符串或字节数组,但不能存储可串行化的对象。
为了增加灵活性,可以有多个并行的树。每个程序用户分别有一棵树;另外还有一棵系统树,可以用于存放所有用户的公共信息。 Preferences 类使用操作系统的“当前用户”概念来访问适当的用户树。
要访问树中的一个节点,需要从用户或系统根开始:
Preferences root_user = Preferences.userRoot(); // 用户
Preferences root_system = Preferences.systemRoot(); // 系统
然后就可以访问节点:
Preferences node = root.node("/com/mycompany/myapp"); // 直接提供节点路径点
// 路径名等于类的包名,可以通过以下便捷方式来获得节点
Preferences node1 = Preferences.userNodeForPackage(obj.getClass()); //
Preferences node2 = Preferences.systemNodeForPackage(obj.getClass());
一般来说,obj 往往是
this
引用。
然后就可以通过以下方法访问键/值:
String get(String key, String defaval);
int getInt(String key, int defaual);
long getLong(String key, long defaual);
float getFloat(String key, float defaual);
double getDouble(String key, double defaual);
boolean getBoolean(String key, boolean defaual);
byte[] getByteArray(String key, byte[] defaual);
值得注意的是,读取信息时必须指定一个默认值。
当然也有对应的 put
方法想存储库写数据:
put(String key, String value);
putInt(String key, int value);
...
可以通过 keys()
来拿到一个节点中存储的所有键。
Preferences 可以导出/导出一个子树的首选项来更灵活的使用 Preferneces :
// 导出
void exportSubtree(OutputStream out); // 导出子树
void exportNode(OutputStream out); // 导出节点
// 导入
void importPrefrences(InputStream in);
// like export
OutputStream out = new FileOutputStream("program.xml");
node.exportSubtree(out);
// like import
InputStream in = new FileInputStram("program.xml");
Preferences.importPreferences(in);