Properties提供的应用程序解决方案主要存在两个问题:
(1)配置文件不能放在主目录中,因为某些OS(如Win9X)没有主目录的概念;
(2)没有标准的文件命名规则,存在文件名冲突的可能性。
Java中的Preferences类可以解决这些问题。Preferences提供一个存储配置信息的中心知识库,与平台无关。在Windows系统中,它存储在注册表中,在Linux中存储在本地文件系统中。它的实现是透明的,程序员无需深究它的底层是如何实现的。
Preferences的中心知识库是树状结构,因此可以避免文件名冲突。每个用户都有一棵树,存放与本用户有关的配置;还有一个系统树,存放全体用户的公共信息。内部的配置信息仍然以key-value的结构进行存储。
Preferences的使用步骤如下:
(1)获得根节点
Preferences root = Preferences.userRoot();
Preferences root = Preferences.systemRoot();
如果配置信息位于用户树,则获取用户树的根节点,否则获取系统树根节点;
(2)获取配置节点
preferences = root.node("path");
path是配置节点相对于根节点的路径;
如果节点的路径名与类的包名相同,则可通过类的对象直接获得配置节点:
Preferences node = Preferences.userNodeForPackage(this.getClass());
Preferences node = Preferences.systemNodeForPackage(this.getClass());
(3)读取配置项
String title = preferences.get("title", "default title");
Preferences要求读取配置项时必须指定默认值。因为在实际环境中总会有各种不如意,比如系统中还没有中心知识库,或者网络暂时不可用等等。
(4)设置配置项
preferences.put(key, value);
(5)同步配置项
preferences.flush();
flush()方法用于立即将配置项写入到文件中。
下面是Preferences类中的常用方法:
示例代码如下:
PreferencesDemo.java
package ConfigByPreferencesDemo; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.prefs.BackingStoreException; import java.util.prefs.InvalidPreferencesFormatException; import java.util.prefs.Preferences; import javax.swing.*; /* * 功能:演示Preferences的用法,实现JFrame窗体参数的修改、保存以及导入导出到xml文件中。 * 版本:20150807 * 结构:PreferencesDemo[主窗体],PreferencesDialog */ public class PreferencesDemo extends JFrame { private Preferences preferences;//配置内容 public PreferencesDemo() { // 加载配置 loadPreferences(); // 设置窗体属性 initFrame(); } public void loadPreferences() { /* * 加载配置,它位于注册表 */ Preferences root = Preferences.userRoot();//HKEY_CURRENT_USER\Software\JavaSoft\Prefs preferences = root.node("/com/horstmann/corejava"); } public void updatePreferencesValue(String key, String value){ /* * 功能:更新Preferences的内容 */ preferences.put(key, value); } public void flushPreferences() { /* * 功能:将最新Preferences的值写入配置文件 */ try { preferences.flush(); } catch (BackingStoreException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public String getPreferencesValue(String key){ /* * 功能:根据key获取configProperties中对应的value */ return preferences.get(key, "0"); } public void exportPreferences(OutputStream out) { /* * 导出配置 */ try { preferences.exportSubtree(out); out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BackingStoreException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void importPreferences(InputStream in) { /* * 导入配置 */ try { Preferences.importPreferences(in); in.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (InvalidPreferencesFormatException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } public void initFrame() { //获取参数,如果不存在则取默认值 String left = preferences.get("left", "0"); String top = preferences.get("top", "0"); String width = preferences.get("width", "300"); String height = preferences.get("height", "200"); String title = preferences.get("title", "default title"); JMenuBar menubar = new JMenuBar(); JMenu windowMenu = new JMenu("Window"); windowMenu.setMnemonic('W'); JMenuItem preferencesItem = new JMenuItem("Preferences"); preferencesItem.setMnemonic('P'); preferencesItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub PreferencesDialog optionsDialog = new PreferencesDialog(PreferencesDemo.this); optionsDialog.setVisible(true); } }); setJMenuBar(menubar); menubar.add(windowMenu); windowMenu.add(preferencesItem); setBounds(Integer.parseInt(left), Integer.parseInt(top), Integer.parseInt(width), Integer.parseInt(height)); setTitle(title); setDefaultCloseOperation(EXIT_ON_CLOSE); } public static void main(String[] args) { // TODO Auto-generated method stub PreferencesDemo preferencesDemo = new PreferencesDemo(); preferencesDemo.setVisible(true); } }
PreferencesDialog.java
package ConfigByPreferencesDemo; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import javax.swing.*; import javax.swing.filechooser.*; /* * @功能:修改配置对话框 * @版本:20150807 */ class PreferencesDialog extends JDialog { PreferencesDemo preferencesDemo;// 父窗体 private JTextField xField; private JTextField yField; private JTextField widthField; private JTextField heightField; private JTextField titleField; private JButton importButton;// 导入配置 private JButton exportButton;// 导出配置 private JButton saveButton;// 保存 private JButton cancelButton;// 取消 private JFileChooser fileChooser;// 文件选择器,用于导入导出配置 public PreferencesDialog(PreferencesDemo parent) { super(parent, true); preferencesDemo = parent; // 提取主配置信息,作为控件的默认值 String xPosition = preferencesDemo.getPreferencesValue("left"); String yPosition = preferencesDemo.getPreferencesValue("top"); String width = preferencesDemo.getPreferencesValue("width"); String height = preferencesDemo.getPreferencesValue("height"); String title = preferencesDemo.getPreferencesValue("title"); // 本UI包含2个panel JPanel inputPanel = new JPanel(); JPanel buttonPanel = new JPanel(); // 构造inputPanel inputPanel.setLayout(new GridLayout()); inputPanel.add(new JLabel("xPosition:")); xField = (JTextField) inputPanel.add(new JTextField(xPosition)); inputPanel.add(inputPanel.add(new JLabel("yPosition:"))); yField = (JTextField) inputPanel.add(new JTextField(yPosition)); inputPanel.add(inputPanel.add(new JLabel("witdh:"))); widthField = (JTextField) inputPanel.add(new JTextField(width)); inputPanel.add(inputPanel.add(new JLabel("height:"))); heightField = (JTextField) inputPanel.add(new JTextField(height)); inputPanel.add(inputPanel.add(new JLabel("title:"))); titleField = (JTextField) inputPanel.add(new JTextField(title)); inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); // 构造buttonPanel importButton = new JButton("import"); importButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { InputStream in = null; if (fileChooser.showSaveDialog(PreferencesDialog.this) == JFileChooser.APPROVE_OPTION) { try { in = new FileInputStream(fileChooser.getSelectedFile()); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } preferencesDemo.importPreferences(in);//导入配置内容 int result = JOptionPane.showConfirmDialog(PreferencesDialog.this, "是否立即更新窗体?", "导入成功", JOptionPane.YES_NO_OPTION); if(result == JOptionPane.YES_OPTION){ validateParentWindow();//更新父窗体界面 } } } }); exportButton = new JButton("export"); exportButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (fileChooser.showSaveDialog(PreferencesDialog.this) == JFileChooser.APPROVE_OPTION) { try { OutputStream out = new FileOutputStream(fileChooser .getSelectedFile()); preferencesDemo.exportPreferences(out);//导出配置内容 } catch (Exception e2) { // TODO: handle exception e2.printStackTrace(); } } JOptionPane.showMessageDialog(PreferencesDialog.this, "导出成功"); setVisible(false); } }); saveButton = new JButton("save"); saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { preferencesDemo.updatePreferencesValue("left", xField.getText() .trim()); preferencesDemo.updatePreferencesValue("top", yField.getText() .trim()); preferencesDemo.updatePreferencesValue("width", widthField .getText().trim()); preferencesDemo.updatePreferencesValue("height", heightField .getText().trim()); preferencesDemo.updatePreferencesValue("title", titleField .getText().trim()); preferencesDemo.flushPreferences();// 写入配置文件 int result = JOptionPane.showConfirmDialog(PreferencesDialog.this, "是否立即更新窗体?", "保存成功", JOptionPane.YES_NO_OPTION); if(result == JOptionPane.YES_OPTION){ validateParentWindow();//更新父窗体界面 } } }); cancelButton = new JButton("Cancel"); cancelButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub setVisible(false); } }); buttonPanel.add(importButton); buttonPanel.add(exportButton); buttonPanel.add(saveButton); buttonPanel.add(cancelButton); buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); // 构造主框架 getContentPane().setLayout(new BorderLayout()); getContentPane().add(inputPanel, BorderLayout.CENTER); getContentPane().add(buttonPanel, BorderLayout.SOUTH); // 设置窗体属性 setTitle("更改主窗体配置"); setLocationRelativeTo(inputPanel); setDefaultCloseOperation(DISPOSE_ON_CLOSE); pack(); // 初始化文件选择器 initFileChooser(); } private void validateParentWindow(){ setVisible(false); preferencesDemo.initFrame(); preferencesDemo.validate(); } private void initFileChooser() { fileChooser = new JFileChooser(); fileChooser.setCurrentDirectory(new File(".")); fileChooser.setFileFilter(new FileFilter() { @Override public String getDescription() { // TODO Auto-generated method stub return "XML files"; } @Override public boolean accept(File f) { // TODO Auto-generated method stub return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory(); } }); } }
运行效果如下:
程序初始界面
配置导入导出-文件选择界面
配置更改后询问是否更新窗体