亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 3773 | 回復(fù): 0
打印 上一主題 下一主題

用 Preferences API 存儲(chǔ)對(duì)象 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2010-02-25 10:42 |只看該作者 |倒序?yàn)g覽

用 Preferences API 存儲(chǔ)對(duì)象
轉(zhuǎn)自:
http://www.ibm.com/developerworks/cn/java/j-prefapi/
如果您的數(shù)據(jù)可以表示為簡單對(duì)象,那么可以使用這個(gè) API 來存儲(chǔ)









級(jí)別: 初級(jí)
Greg Travis
(
[email=mito@panix.com?subject=用 Preferences API 存儲(chǔ)對(duì)象&cc=mito@panix.com]mito@panix.com[/email]
), 自由程序員
2003 年 11 月 24 日
Preferences API,一種在 JDK 1.4 中引入的輕型的、跨平臺(tái)的持久性 API,是為存儲(chǔ)少量數(shù)據(jù)(字符串、簡單字節(jié)數(shù)組等)而設(shè)計(jì)的,它不是為了要成為傳統(tǒng)數(shù)據(jù)庫的一個(gè)接口。不過,如果您的數(shù)據(jù)可以表示為一個(gè)簡單的對(duì)象,那么它可以成為一個(gè)高效的存儲(chǔ)設(shè)備。本文介紹了這個(gè)API,解釋了對(duì)象是如何存儲(chǔ)的,并展示了所進(jìn)行的過程,提供了完成這些工作的代碼庫。
Preferences API 是輕型的、跨平臺(tái)的持久性 API,它是在 JDK 1.4中引入的。它不是為了為傳統(tǒng)數(shù)據(jù)庫引擎提供一個(gè)接口,而是用恰當(dāng)?shù)摹⒉僮飨到y(tǒng)特定的后端以實(shí)現(xiàn)真正的持久性。這個(gè) API 是用來存儲(chǔ)少量數(shù)據(jù)的。事實(shí)上,它的名字本身就表明它通常用于存儲(chǔ)用戶特定的設(shè)置或者首選項(xiàng),如字體大小或者窗口布局(當(dāng)然,您可以在其中存儲(chǔ)任何您想要存儲(chǔ)的內(nèi)容)。
Preferences API 設(shè)計(jì)為存儲(chǔ)字符串、數(shù)字、布爾值、簡單字節(jié)數(shù)組等。在本文中,我們將為您展示如何用 Preferences API 存儲(chǔ)對(duì)象,并提供了一個(gè)為您處理細(xì)節(jié)的工作庫。如果您的數(shù)據(jù)可以容易地表示為簡單對(duì)象而不是像字符串和數(shù)字這種分離的值時(shí),它會(huì)很有用。
我們首先對(duì)該 API 作一簡短討論,包括一些使用它的簡單例子,然后詳細(xì)討論如何使用這個(gè) API 存儲(chǔ)對(duì)象,并給出為我們完成這項(xiàng)工作的代碼。我們還展示了一些使用這個(gè) API 的例子。
為什么設(shè)計(jì) Preferences API?
如果說 Preferences API 主要是為讓 Java 程序訪問 Microsoft Windows 注冊(cè)表而創(chuàng)建的,一定會(huì)讓人感到意外。為什么我要這么說呢?這個(gè) API 的設(shè)計(jì)類似于 Windows 注冊(cè)表,本文前三段中的大部分說明也同樣適用于注冊(cè)表。
不過,Preferences API 就像所有 Java 語言一樣,是以跨平臺(tái)為目的的,所以它在非 Windows 系統(tǒng)上至少可以工作得一樣好(當(dāng)然,本文中的代碼是跨平臺(tái)的)。
Preferences API 規(guī)范沒有規(guī)定如何實(shí)現(xiàn)這個(gè) API,只規(guī)定了它必須做什么。Java 運(yùn)行時(shí)環(huán)境(Java Runtime Environment JRE)的每一個(gè)實(shí)現(xiàn)對(duì)這個(gè) API 都可以有不同的實(shí)現(xiàn)。許多非注冊(cè)表的實(shí)現(xiàn)將 API 數(shù)據(jù)存儲(chǔ)在一個(gè) XML 格式的文件中,這個(gè)文件也許是在用戶的主目錄中或者在一個(gè)共享目錄中。
與 Windows 注冊(cè)表一樣,Preferences API 使用層次樹結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù)。起始點(diǎn)是一個(gè) root node (根節(jié)點(diǎn)是樹的根基,所有其他節(jié)點(diǎn)都是這個(gè)節(jié)點(diǎn)的后代)。節(jié)點(diǎn)可以包含命名的值以及其他節(jié)點(diǎn)。不同的程序?qū)⑺鼈兊臄?shù)據(jù)存儲(chǔ)在樹的不同位置上,所以它們不會(huì)彼此沖突。正如我們將要看到的,Preferences API 采用了特殊的方法幫助防止這種沖突。
我們將首先簡單看一下 Preferences API 是如何工作的以及如何使用它。




回頁首
使用 Preferences
理解 Preferences API 的最好方法是使用它。需要做的第一件事是訪問根節(jié)點(diǎn):
Preferences root = Preferences.userRoot();
這一行代碼返回?cái)?shù)據(jù)樹的 user root。前面我們說系統(tǒng)中的所有數(shù)據(jù)都存儲(chǔ)在一個(gè)樹中。不過,這并不完全正確 -- 事實(shí)上,有 個(gè)數(shù)據(jù)樹 -- 用戶樹和系統(tǒng)樹。這兩個(gè)樹的行為完全相同,但是它們有不同的目的。系統(tǒng)樹用于存儲(chǔ)所用戶都可以使用的數(shù)據(jù),而用戶樹對(duì)于每一個(gè)用戶是不同的。
這兩個(gè)樹天生就有不同的目的。您要將字體首選項(xiàng)存儲(chǔ)在用戶樹中,因?yàn)檫@是用戶特定的內(nèi)容。另一方面,您要將程序位置存儲(chǔ)在系統(tǒng)樹中,因?yàn)槲恢脤?duì)于所有用戶是相同的,并且所有用戶都可能用到它。
小型程序會(huì)使用系統(tǒng)樹或者用戶樹,但是不會(huì)同時(shí)使用這兩者。大型應(yīng)用程序可能同時(shí)使用這兩種樹。在本文中,我們將只針對(duì)用戶樹,要記住用戶和系統(tǒng)樹的行為是一樣的。
現(xiàn)在讓我們看一下如何用 Preferences API 讀取和寫入簡單的值。




回頁首
獲得一個(gè)值
當(dāng)您得到根節(jié)點(diǎn)后,就用它讀取和寫入值。下面是如何寫入一個(gè)字體大。
root.putInt( "fontsize", 10 );
下面是在這之后將它讀出來的方法:
int fontSize = prefs.getInt( "fontsize", 12 );
注意 getInt() 需要一個(gè)默認(rèn)值 -- 在這里是12。
當(dāng)然,您可以讀取和寫入整數(shù)之外的值。可以讀取和寫入許多基本 Java 類型。還可以將節(jié)點(diǎn)存儲(chǔ)在其他節(jié)點(diǎn)中,如這個(gè)例子所示:
Preferences child = parent.node( "child" );
這就是 Preferences API 的全部內(nèi)容 -- 剩下的就是細(xì)節(jié)使用了,我們將在下一節(jié)討論其中一個(gè)細(xì)節(jié)。




回頁首
獲得一個(gè)包的節(jié)點(diǎn)
不難想像兩個(gè)不同的程序員可能希望存儲(chǔ)不同的字體大小,如果他們決定以同一個(gè)名字“font size”存儲(chǔ)他們的值,那么我們就有問題了。一個(gè)程序的首選項(xiàng)會(huì)影響另一個(gè)程序。
解決方法是將內(nèi)容存儲(chǔ)在包特定的位置上,像這樣:
Preferences ourRoot = Preferences.userNodeForPackage( getClass() );
userNodeForPackage() 方法取一個(gè) Class 對(duì)象并返回這個(gè)類特定的節(jié)點(diǎn)。這樣,每一個(gè)應(yīng)用程序 -- 假定它是在其自己的包中 -- 都會(huì)有自己的首選項(xiàng)節(jié)點(diǎn)。
對(duì)于 Preferences API 的工作方式有了很好的了解后,我們還需要知道如何擴(kuò)展它以便對(duì)對(duì)象進(jìn)行處理。




回頁首
存儲(chǔ)對(duì)象
這就是我們希望將對(duì)象寫入 Preferences 樹的理想方法:
清單 1. 將對(duì)象寫入 Preferences 樹的理想方法
Font font = new Font( ... );
Preferences prefs = Preferences.userNodeForPackage( getClass() );
prefs.putObject( "font", font );
不過,不幸的是,Preferences 對(duì)象沒有 putObject() 和 getObject() 方法。但是我們會(huì)盡量做到接近這一點(diǎn)。我們將在一個(gè)名為 PrefObj 的類中實(shí)現(xiàn)這些方法。以下是我們的做法:
清單 2. 實(shí)現(xiàn) putObject() 和 getObject()
Font font = new Font( ... );
Preferences prefs = Preferences.userNodeForPackage( getClass() );
PrefObj.putObject( prefs, "font", font );
我們已經(jīng)盡量做到在 Preferences 類中得到一個(gè)添加方法。
下一節(jié),我們將看一看 getObject() 和 putObject() 是如何實(shí)現(xiàn)的。




回頁首
將對(duì)象轉(zhuǎn)換為字節(jié)數(shù)組
我們?cè)谶@里使用的技術(shù)用到了兩個(gè)技巧。第一個(gè)技巧是將對(duì)象轉(zhuǎn)變?yōu)橐粋(gè)字節(jié)數(shù)組。這樣做的原因很簡單:盡管 Preferences 對(duì)象不處理對(duì)象,但是它可以處理字節(jié)數(shù)組。
幸運(yùn)的是,我們不需要從頭開始 -- 它已經(jīng)建立在 Java 語言中了。有幾種方式將對(duì)象轉(zhuǎn)換為字節(jié)數(shù)組,下面展示了我們?cè)?PrefObj 類中是如何做的:
清單 3. 將對(duì)象轉(zhuǎn)換為字節(jié)數(shù)組
static private byte[] object2Bytes( Object o ) throws IOException {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  ObjectOutputStream oos = new ObjectOutputStream( baos );
  oos.writeObject( o );
  return baos.toByteArray();
}
這里的關(guān)鍵是 ObjectOutputStream 類 -- 它是實(shí)際完成將對(duì)象轉(zhuǎn)換為字節(jié)流這個(gè)魔術(shù)的類。通過用 ObjectOutputStream 包住 ByteArrayOutputStream ,我們就將字節(jié)流轉(zhuǎn)換為字節(jié)數(shù)組。
還有一種使用其他方式的方法:
清單 4. 將字節(jié)數(shù)組轉(zhuǎn)換為對(duì)象
static private Object bytes2Object( byte raw[] )
    throws IOException, ClassNotFoundException {
  ByteArrayInputStream bais = new ByteArrayInputStream( raw );
  ObjectInputStream ois = new ObjectInputStream( bais );
  Object o = ois.readObject();
  return o;
}
一定要記 ObjectOutputStream 只處理實(shí)現(xiàn)了 java.io.Serializable 接口的對(duì)象。幸運(yùn)的是,這包括了幾乎所有核心 Java 庫中的對(duì)象以及您的程序中所有聲明為實(shí)現(xiàn) Serializable 的對(duì)象。
正如我在前面提到的,Preferences API 的確可以對(duì)字節(jié)數(shù)組進(jìn)行處理。不過,我們?cè)谶@里構(gòu)造的字節(jié)數(shù)組并不是很正確,我們將在下一節(jié)看到這一點(diǎn)。




回頁首
將對(duì)象拆分為片段
Preferences API 對(duì)可以存儲(chǔ)在它里面的數(shù)據(jù)大小有限制。具體就是字符串限制為 MAX_VALUE_LENGTH 字符。字節(jié)數(shù)組限制為 MAX_VALUE_LENGTH 長度 75%,因?yàn)樽止?jié)數(shù)組是通過編碼為字符串存儲(chǔ)的。
另一方面,一個(gè)對(duì)象可以為任意大小,所以我們需要將它分為幾部分。當(dāng)然,最容易的方法是首先將它轉(zhuǎn)換為一個(gè)字節(jié)數(shù)組,然后將字節(jié)數(shù)組拆開。下面是拆開字節(jié)數(shù)組的代碼,它也來自于 PrefObj :
清單 5. 將字節(jié)數(shù)組拆分為可消化的大小
static private byte[][] breakIntoPieces( byte raw[] ) {
  int numPieces = (raw.length + pieceLength - 1) / pieceLength;
  byte pieces[][] = new byte[numPieces][];
  for (int i=0; i raw.length) endByte = raw.length;
    int length = endByte - startByte;
    pieces = new byte[length];
    System.arraycopy( raw, startByte, pieces, 0, length );
  }
  return pieces;
}
這里沒有什么復(fù)雜的內(nèi)容 -- 我們只是創(chuàng)建一個(gè)數(shù)組的數(shù)組,每一個(gè)長度為最大 pieceLength的字節(jié)長度(pieceLength 是 MAX_VALUE_LENGTH 的3/4)。相應(yīng)地,有另一種方法將各個(gè)部分再合并到一起:
清單 6. 將片段重新組裝為完整的字節(jié)數(shù)組
static private byte[] combinePieces( byte pieces[][] ) {
  int length = 0;
  for (int i=0; ipieces.length; ++i) {
    System.arraycopy( pieces, 0, raw, cursor, pieces.length );
    cursor += pieces.length;
  }
  return raw;
}
這個(gè)例程檢查所有片段的總長度并創(chuàng)建一個(gè)具有這種長度的新數(shù)組。然后將片段一個(gè)一個(gè)地拷貝進(jìn)去。




回頁首
讀取和寫入片段
這里我們使用第二個(gè)技巧 -- 將值轉(zhuǎn)換為節(jié)點(diǎn)。一般來說,當(dāng)我們用 Preferences API 存儲(chǔ)值時(shí),我們將它放到首選項(xiàng)數(shù)據(jù)樹中一個(gè)節(jié)點(diǎn)的 slot 中。
但是我們不能在這里真的這樣做。即使一個(gè)對(duì)象只有一個(gè)值,我們也要將它轉(zhuǎn)換為一組固定長度的字節(jié)數(shù)組。如果我們只有一個(gè)字節(jié)數(shù)組,寫入數(shù)據(jù)樹中的 slot 會(huì)很容易,因?yàn)?Preferences API 直接支持字節(jié)數(shù)組。但是這行不通,因?yàn)槲覀冇卸鄠(gè)數(shù)組。
技巧是為每一個(gè)對(duì)象分配一個(gè)節(jié)點(diǎn)。讓我們弄清楚它的意義。
通常,將值存儲(chǔ)在節(jié)點(diǎn)的多個(gè) slot 的其中之一。但是我們準(zhǔn)備為每一個(gè)對(duì)象創(chuàng)建一個(gè)節(jié)點(diǎn), 并將字節(jié)數(shù)組存儲(chǔ)到該節(jié)點(diǎn)的 slot 中。讓我們說的更具體一些。如果可以,我們會(huì)將一個(gè)對(duì)象存儲(chǔ)到單個(gè) slot 中:
清單 7. 將一個(gè)對(duì)象存儲(chǔ)到單個(gè) slot 中
Preferences parent = ....;
parent.putObject( "child", object );
但是我們不能這么做,因?yàn)?Preferences 沒有 putObject() 方法。相反,我們創(chuàng)建一個(gè)節(jié)點(diǎn)并將字節(jié)數(shù)組存儲(chǔ)到其中,如下所示:
清單 8. 將字節(jié)數(shù)組存儲(chǔ)到一個(gè)節(jié)點(diǎn)中
Preferences parent = ....;
Preferences child = parent.node( "child" );
for (int i=0; i
這樣,不是將一個(gè)值存儲(chǔ)到一個(gè)稱為“child”的 slot 中,我們將幾個(gè)值存儲(chǔ)到一個(gè)稱為 “child”的節(jié)點(diǎn)中。這些值是用數(shù)字鍵 -- “0”、“1”、“2”等存儲(chǔ)的。
使用數(shù)字鍵可以使后面讀取片段時(shí)更容易:
清單 9. 讀取容易讀的片段
Preferences parent = ....;
Preferences child = parent.node( "child" );
for (int i=0; i
在下一節(jié),我們將看一下結(jié)合所有這些步驟的例程。




回頁首
將所有內(nèi)容合到一起
PrefObjs 有一個(gè)名為 putObject() 的靜態(tài)方法,它調(diào)用在前面清單
3
、
5

8
中描述的方法。其內(nèi)容如下:
清單 10. 方法 putObject() 使用其他方法來寫入片段
static public void putObject( Preferences prefs, String key, Object o )
    throws IOException, BackingStoreException, ClassNotFoundException {
  byte raw[] = object2Bytes( o );
  byte pieces[][] = breakIntoPieces( raw );
  writePieces( prefs, key, pieces );
}
方法 putObject() 將整個(gè)過程分為三步,分別嵌入我們?cè)谇懊嬗懻撨^的三個(gè)方法。它將對(duì)象轉(zhuǎn)換為字節(jié)數(shù)組(
清單 3
)、將數(shù)組分解為更小的數(shù)組(
清單 5
)、然后將片段寫入 Preferences API。
有一個(gè)用于讀取的類似方法:
清單 11. 方法 getObject() 對(duì)寫入片段做同樣的事情
static public Object getObject( Preferences prefs, String key )
    throws IOException, BackingStoreException, ClassNotFoundException {
  byte pieces[][] = readPieces( prefs, key );
  byte raw[] = combinePieces( pieces );
  Object o = bytes2Object( raw );
  return o;
}
這個(gè)方法從 Preferences API 中讀取片段,并將它們結(jié)合為單個(gè)字節(jié)數(shù)組,然后將它轉(zhuǎn)換為對(duì)象。




回頁首
存儲(chǔ)信息
正如您所看到的,這是一種使用 Preferences API 所具有的功能的簡潔方式,實(shí)現(xiàn)了它 本來不具備的功能。這是一種擴(kuò)展現(xiàn)有庫的好方法。理論上,您可以改變庫或者創(chuàng)建子類,但是這樣有可能會(huì)干擾其他使用 Preferences API 的程序。而使用這種方式,您可以保持原來的 API 不變,同時(shí)以一種干凈、有用的方式擴(kuò)展它。
參考資料

關(guān)于作者


Greg Travis 是居住在紐約的一個(gè)自由 Java 程序員和技術(shù)文章撰稿人。他于 1992 年開始其編程生涯,在高端 PC 游戲領(lǐng)域花了三年時(shí)間。1995 年,他加入了 EarthWeb,在這里他開始用 Java 編程語言開發(fā)新技術(shù)。1997 年以后,Greg 一直擔(dān)任各種 Web 技術(shù)的顧問,其專長是實(shí)時(shí)圖像和聲音。他的興趣包括算法優(yōu)化、編程語言設(shè)計(jì)、信號(hào)處理(重點(diǎn)在音樂)、以及實(shí)時(shí) 3D 圖形。他也是由 Manning Publications 出版的“ JDK 1.4 Tutorial”一書的作者。可以通過
[email=mito@panix.com?cc=mito@panix.com]mito@panix.com[/email]
與他聯(lián)系。


本文來自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u3/94064/showart_2186459.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP