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(); } }); } }
運行效果如下:
程序初始界面
配置導入導出-文件選擇界面
配置更改后詢問是否更新窗體