Java首选项Preferences

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CodingEnding/article/details/72580201

前言

对一款人性化的应用来说,往往需要存储用户的偏好设置,例如字体大小、应用风格等个性化的设置数据。Java应用具有跨平台的特性,就更需要一种平台无关的存储手段。Java官方给出的解决方案是Preferences首选项,本文就来简单讲解一下Preferences的使用。

Preferences的存储模式

首先,我们需要知道Preferences为什么可以实现跨平台存储数据。实际上,在不同的操作系统中,Preferences底层的存储方式是不一样的。例如,在Windows下是将数据存储在注册表中,而在Linux下则是将数据存储在文件系统中的。当然,对于程序员来说,这些都是透明的。

Preferences中,使用了树状结构来进行数据的存储,这主要是为了避免文件名冲突。我们需要知道的是,Preferences中有着两棵独立的树。一棵是用户首选项树,一棵是系统首选项树。在用户首选项树中,一般存储应用程序的个性化设置,如字体大小、字体颜色等。而系统首选项树是全局共享的,一般用来设置应用程序的配置数据。通常我们使用用户首选项树即可。

在每棵首选项树中,存在着许多节点,我们的数据就存储在这些节点中。每个节点都有一个节点名,并且节点名可以不唯一,但是节点名中不可以包含“/”字符。同时,每个节点都有一个绝对路径名,这是唯一的。首选项树的根节点绝对路径名是“/”,它的子节点则是“/”+子节点名,其他节点的绝对路径命名方式与此类似。对根节点之外的任何一个节点来说,其绝对路径都是父节点的绝对路径+“/”+当前节点名。在每个节点对应的Preferences对象中,使用键值对的方式来存储和获取数据,这类似于HashMap的使用方式。

基本操作

获取Preferences对象

首先我们需要获取一个Preferences对象。Preferences提供了两个静态方法用于获取首选项树的根节点。

//获取用户首选项树根节点
public static Preferences userRoot()
//获取系统首选项树根节点
public static Preferences systemRoot()

得到根节点后,就可以通过node方法获取我们需要的子节点了。node方法原型如下:

public abstract Preferences node(String pathName);

对于node方法,我们可以传入节点的相对路径名或绝对路径名。以“/”字符开头的就是绝对路径名,而不以“/”开头的则是相对于当前节点的相对路径名。如果该节点不存在,系统将会创建该节点,否则就返回已存在的节点。接下来我们尝试以当前包名作为路径获取一个子节点对应的Preferences对象:

public class PreferencesDemo {
    public static void main(String[] args) {
        String absolutePath="/com/example/preferences";
        Preferences preferences=Preferences.userRoot().node(absolutePath);
        System.out.println(preferences);
    }
}

输出结果:

User Preference Node: /com/example/preferences

可以看到,通过将当前包名作为绝对路径,我们已经成功获得了一个Preferences对象。接下来,我们就可以通过这个对象写入和读取数据了。

写入数据/读取数据

Preferences提供了一系列putXXX方法用于写入不同类型的数据,方法原型如下:

abstract void put(String key, String value) 
abstract void putBoolean(String key, boolean value) 
abstract void putByteArray(String key, byte[] value)  
abstract void putDouble(String key, double value) 
abstract void putFloat(String key, float value) 
abstract void putInt(String key, int value) 
abstract void putLong(String key, long value) 

相应的,Preferences也提供了一系列getXXX方法读取不同类型的数据,方法原型如下:

abstract String get(String key, String def) 
abstract boolean getBoolean(String key, boolean def) 
abstract byte[] getByteArray(String key, byte[] def) 
abstract double getDouble(String key, double def) 
abstract float getFloat(String key, float def) 
abstract int getInt(String key, int def) 
abstract long getLong(String key, long def) 

需要注意的是,所有的getXXX方法都需要传入一个默认值,这是为了在首选项不可用时依旧不会影响应用的正常运行,有利于提高程序的鲁棒性。以下演示向首选项写入和读取字符串:

String defStr=preferences.get("key_str","默认值");
preferences.put("key_str","新的值");
String newStr=preferences.get("key_str","默认值");
System.out.println(defStr);
System.out.println(newStr);

输出结果:

默认值
新的值

刷新数据

Preferences中,默认使用异步的方式写入数据,某些时候我们希望数据可以马上更新,就需要对数据进行刷新操作。这时,就可以使用flush这个方法,其原型如下:

abstract void flush()  

删除数据

Preferences提供了两个删除数据的方法。remove用于删除指定键对应的值,removeNode则用于删除当前节点。这两个方法的原型如下:

abstract void remove(String key)
abstract void removeNode()

导入/导出首选项数据

某些时候,我们希望从外部导入应用的偏好设置,或者将当前应用的偏好设置导出进行备份。这时我们就可以使用Preferences提供的导入/导出方法。在这个过程中,数据的载体是XML文件。

static void importPreferences(InputStream is)
abstract void exportNode(OutputStream os)
abstract void exportSubtree(OutputStream os)

importPreferences用于将XML文件中的数据导入首选项系统。exportNode用于导出当前节点存储的数据,但是并不会导出当前节点的子节点中的数据exportSubtree则会导出当前节点及其子节点的所有数据。以下演示如何将当前节点的数据导出到文件中:

public class PreferencesDemo {
    public static void main(String[] args) {
        .........
        try {
            FileOutputStream outStream=new FileOutputStream("preferences.xml");
            preferences.exportNode(outStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (BackingStoreException e) {
            e.printStackTrace();
        }
    }
}

以上程序会将当前节点的数据导出到项目根目录下的“preferences.xml”文件中,文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<preferences EXTERNAL_XML_VERSION="1.0">
  <root type="user">
    <map/>
    <node name="com">
      <map/>
      <node name="example">
        <map/>
        <node name="preferences">
          <map>
            <entry key="key_str" value="新的值"/>
          </map>
        </node>
      </node>
    </node>
  </root>
</preferences>

一个典型的例子

接下来,我们演示一个Preferences的使用场景。在程序首次运行时,将会输出欢迎语句,但是当程序再次运行时,将会输出其他内容。

public class PreferencesDemo {
    public static final String KEY_FIRST_RUN="is_first_run";

    public static void main(String[] args) {
        String absolutePath="/com/example/preferences";
        Preferences preferences=Preferences.userRoot().node(absolutePath);
        //判断程序是否是第一次运行
        boolean isFirstRun=preferences.getBoolean(KEY_FIRST_RUN,true);
        if(isFirstRun){
            System.out.println("欢迎使用本程序!");
            preferences.putBoolean(KEY_FIRST_RUN, false);
        }else{
            System.out.println("这已经不是一次运行了哦~");
        }
    }
}

第一次运行:

欢迎使用本程序!

第二次运行:

这已经不是一次运行了哦~

猜你喜欢

转载自blog.csdn.net/CodingEnding/article/details/72580201
今日推荐