企業(yè)微信網(wǎng)站建設(shè)品牌營(yíng)銷(xiāo)推廣
首選項(xiàng)API
在桌面程序中,通常都會(huì)存儲(chǔ)用戶首選項(xiàng),如用戶最后處理的文件、窗口的最后位置等。
利用Properties類(lèi)可以很容易的加載和保存程序的配置信息,但有以下缺點(diǎn):
- 有些操作系統(tǒng)沒(méi)有主目錄概念,很難為匹配文件找到一個(gè)統(tǒng)一的位置。
- 配置文件沒(méi)有標(biāo)準(zhǔn)命名,用戶安裝多個(gè)Java應(yīng)用,就更容易發(fā)生命名沖突。
操作系統(tǒng)有一個(gè)存儲(chǔ)配置信息的中心存儲(chǔ)庫(kù),最著名例子就是Window系統(tǒng)中的注冊(cè)表。
Preferences類(lèi)似于一種平臺(tái)無(wú)關(guān)的中心存儲(chǔ)庫(kù),Windows中,Preferences使用注冊(cè)表存儲(chǔ)信息,Linux上信息存儲(chǔ)在本地文件系統(tǒng)中。存儲(chǔ)庫(kù)對(duì)程序員是透明的。
Preferences有一個(gè)樹(shù)狀結(jié)構(gòu),節(jié)點(diǎn)路徑類(lèi)似于/com/mycompany/myapp。
每個(gè)節(jié)點(diǎn)都有一個(gè)單獨(dú)的鍵值對(duì)表,可存儲(chǔ)數(shù)值,字符串,字節(jié)數(shù)組,不建議存儲(chǔ)串行化對(duì)象??梢杂卸鄠€(gè)樹(shù),每個(gè)程序用戶都有一棵樹(shù),類(lèi)似于操作系統(tǒng)的當(dāng)前用戶概念。
訪問(wèn)數(shù)中的一個(gè)節(jié)點(diǎn),需要從用戶或系統(tǒng)根開(kāi)始:
Preferences root = Preferences.userRoot();或者
Preferences root = Preferences.systemRoot();
然后訪問(wèn)節(jié)點(diǎn),可以直接提供一個(gè)節(jié)點(diǎn)路徑名:
Preferences node = root.node("/com/mycompany/myapp");
如果節(jié)點(diǎn)路徑名等于類(lèi)的包名,可以簡(jiǎn)便調(diào)用:
Preferences node = Preferences.userNodeForPackage(obj.getClass());或
Preferences node = Preferences.systemNodeForPackage(obj.getClass());
一般來(lái)說(shuō),obj往往是this引用
得到節(jié)點(diǎn),可以用如下方法訪問(wèn)鍵值表:
String get(String key,String defval)
int getInt(String key,int defval)
double getDouble(String key,double defval)
byte[] getByteArray(String key,byte[] defval)等
讀取信息時(shí)必須指定一個(gè)默認(rèn)值。
如下put方法向存儲(chǔ)庫(kù)寫(xiě)數(shù)據(jù):
put(String key,String value)
putInt(String key,int value)
可以用一下方法枚舉一個(gè)節(jié)點(diǎn)中存儲(chǔ)的所有鍵
String[] keys()
注釋:節(jié)點(diǎn)名和鍵都最多只能有80個(gè)字符,字符串值最多可以有8192個(gè)字符。
類(lèi)似Windows注冊(cè)表的中心存儲(chǔ)庫(kù)通常都存在兩個(gè)問(wèn)題:
- 它們會(huì)變成充斥著過(guò)期信息的垃圾場(chǎng)
- 配置數(shù)據(jù)域存儲(chǔ)庫(kù)糾纏在一起,所有很難把首選項(xiàng)遷移到新平臺(tái)。
提供了第二個(gè)問(wèn)題的解決方案,通過(guò)一下方法導(dǎo)出一個(gè)子樹(shù):
void exportSubtree(OutputStream out)
void exportNode(OutputStream out)
數(shù)據(jù)用XML格式保存,可以已通過(guò)調(diào)用一下方法將數(shù)據(jù)導(dǎo)入到另一個(gè)存儲(chǔ)庫(kù):
void importPreferences(InputStream in)
示例文件,略。
案例:保存窗口位置和文件名,導(dǎo)出首選項(xiàng)后,退出并重啟應(yīng)用,導(dǎo)入首選項(xiàng),窗口和之前一樣,待續(xù)。。。
package preferences;import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.prefs.Preferences;import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;public class ImageViewer {public static void main(String[] args) {EventQueue.invokeLater(()->{var frame = new ImageViewerFrame();frame.setTitle("圖片查看器");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);});}
}class ImageViewerFrame extends JFrame {private static final int DEFAULT_WIDTH = 300;private static final int DEFAULT_HEIGHT = 200;private String image;public ImageViewerFrame() {Preferences root = Preferences.userRoot();Preferences node = root.node("/preferences/ImageViewer");int left = node.getInt("left", 0);int top = node.getInt("top", 0);int width = node.getInt("width", DEFAULT_WIDTH);int height = node.getInt("height", DEFAULT_HEIGHT);setBounds(left, top, width, height);image = node.get("image", null);var label = new JLabel();if(image != null) label.setIcon(new ImageIcon(image));addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {node.putInt("left", getX());node.putInt("top", getY());node.putInt("width", getWidth());node.putInt("height", getHeight());node.put("image", image);}});add(label);//安裝文件選擇器var chooser = new JFileChooser();chooser.setCurrentDirectory(new File("."));//安裝菜單欄var menuBar = new JMenuBar();setJMenuBar(menuBar);var menu = new JMenu("文件");menuBar.add(menu);var openItem = new JMenuItem("打開(kāi)");menu.add(openItem);openItem.addActionListener(event -> {int result = chooser.showOpenDialog(null);if (result == JFileChooser.APPROVE_OPTION) {image = chooser.getSelectedFile().getPath();label.setIcon(new ImageIcon(image));}});var exitItem = new JMenuItem("關(guān)閉");menu.add(exitItem);exitItem.addActionListener(event->System.exit(0));}
}
java.util.prefs.Preferences 1.4
- Preferencs userRoot(),返回調(diào)用程序的用戶的首選項(xiàng)根節(jié)點(diǎn)。
- Preferences systemRoot(),返回系統(tǒng)范圍的首選項(xiàng)根節(jié)點(diǎn)。
- Preferences node(String path),返回從當(dāng)前節(jié)點(diǎn)由給定路徑可以到達(dá)的節(jié)點(diǎn)。如果path是絕對(duì)路徑(也就是說(shuō),以一個(gè)/開(kāi)頭),則從包含這個(gè)首選項(xiàng)節(jié)點(diǎn)的樹(shù)的根節(jié)點(diǎn)開(kāi)始查找。如果給定路徑不存在相應(yīng)的節(jié)點(diǎn),則創(chuàng)建這樣一個(gè)節(jié)點(diǎn)。
- Preferences userNodeForPackage(Class cl)
- Preferences systemNodeForPackage(Class cl),返回當(dāng)前用戶樹(shù)或系統(tǒng)樹(shù)中的一個(gè)節(jié)點(diǎn),其絕對(duì)節(jié)點(diǎn)路徑對(duì)應(yīng)類(lèi)cl的包名。
- String[] keys(),返回屬于這個(gè)節(jié)點(diǎn)的所有鍵。
- String get(String key,String defval)
- int getInt(String key,int defval)
- long getLong(String key,long defval)
- float getFloat(String key,float defval)
- double getDouble(String key,double defval)
- boolean getBoolean(String key,double defval)
- byte[] getByteArray(String key, byte[] defval),返回與給定鍵關(guān)聯(lián)的值,或者如果沒(méi)有值與這個(gè)鍵關(guān)聯(lián)、關(guān)聯(lián)的值類(lèi)型不正確或首選項(xiàng)存儲(chǔ)庫(kù)不可用,則返回所提供的默認(rèn)值。
- void put(String key, String value)
- void putInt(String key, int value)
- void putLong(String key, long value)
- void putFloat(String key,float value)
- void putDouble(String key, double value)
- void putBoolean(String key,boolean value)
- void putByteArray(String key,byte[] value),在這個(gè)節(jié)點(diǎn)存儲(chǔ)一個(gè)值/鍵對(duì)。
- void exportSubtree(OutputStream out),將這個(gè)節(jié)點(diǎn)及其子節(jié)點(diǎn)的首選項(xiàng)寫(xiě)至指令的流。
- void exportNode(OutputStream out),將這個(gè)節(jié)點(diǎn),不包括其子節(jié)點(diǎn)的首選項(xiàng)寫(xiě)至指定的流。
- void importPreferences(InputStream in),導(dǎo)入指定流中包含的首選項(xiàng)。