RMS提供的記錄操作可以實現根據ID直接獲得記錄,或者枚舉出一個表中的所有記錄。
但是枚舉記錄的效率是非常低的,因爲只能比較byte[]數據來確定該記錄是否是所需要的記錄。通過ID獲得記錄是高效而方便的,類似於SQL語句中”selecte byteArrayData from recordStoreName where RecordID = ?”。然而,通常應用程序很難知道某條激流的ID號,而RMS記錄的“主鍵”又僅限於int類型,無法使用其他類型如String作爲“主鍵”來查找。因此,對於需要存取不同類型對象的應用程序而言,就需要一個靈活的RMS操作框架。
我們的基本設想是,如果能使用String作爲“主鍵”來查找記錄,就能非常方便地獲得所需的內容。例如,應用程序設置可以通過"sys.settings"獲得byte[]數組,並依次讀取出設置,用戶登錄信息可以通過"user.info"獲得byte[]數組,再分解出用戶名和口令。
因此,我們實現一個StorageHandler類,提供唯一的RMS訪問接口,使得其他類完全不必考慮底層的RMS操作,只需提供能標識自身的一個String即可。
如果我們能實現一種類似於數據庫索引的查找表,就能根據String關鍵字查找某條記錄。因此,我們使用一個名爲"index"的RecordStore來存儲所有的索引,每一條索引都指向某一條具體記錄的ID,設計一個IndexEntry表示一條索引:
class IndexEntry { private int selfId; // IndexEntry的ID private int recordId; // 對應記錄的ID private String key; // 訪問記錄的Key }
根據索引查找,分3步進行:
1.在名爲"index"的RecordStore中根據String查找對應的IndexEntry。
2.取出IndexEntry,獲得記錄ID號。
3.根據ID號獲得另一個RecordStore的記錄,然後就可以讀取、更新和刪除該記錄。
根據網上的那一篇J2ME最佳實踐之RMS操作(建議先看看這篇),我寫了一個自己的RMS框架,包含完整的代碼。
首先看看示意圖,示意圖總是看着讓我思路清晰一些。
這幅圖摘自J2ME最佳實踐之RMS操作,很明顯我需要兩個RecordStore,一個index存儲String類型的主鍵和RecordId,另一個data存儲記錄。
我爲我的RMS框架也做了一份示意圖,從圖中可以看出我的類結構
- RecordManager——用於操作RecordStore的類,提供了一些操作RMS的基本方法
- StoreHandler——倉庫處理類,提供了LoadData、StoreData、StoreIndex方法
- IndexEntry——主鍵、記錄ID實體類,對應上圖RecordStore中的index
- IStore——接口,提供SaveData(保存數據)、ReadData(讀取數據)的方法,需要進行存儲的對象,只需要對象對應的類實現IStore接口
- User,Person——實體類,實現IStore接口
RecordManager類:
package com.org.sunny.rms; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import javax.microedition.rms.RecordStore; import javax.microedition.rms.RecordStoreException; /** * * @author Administrator */ public class RecordManager { //RMS是否打開 boolean isOpen = false; public RecordStore rs; /** * 打開RMS,分別可以傳入index和data * index存儲主鍵、RecordId * data存儲數據 * @param rsName */ public void open(String rsName) { try { rs = RecordStore.openRecordStore(rsName, true, RecordStore.AUTHMODE_ANY, true); } catch (RecordStoreException ex) {//存儲系統異常 System.out.print(ex); } catch (IllegalArgumentException ex) {//參數錯誤異常 System.out.println(ex); } } /** * 關閉RMS */ public void close() { try { rs.closeRecordStore(); } catch (Exception ex) { ex.printStackTrace(); } } /** * 添加一條記錄,並返回添加的記錄ID * @param rsName * @param data * @return */ public int add(String rsName, byte[] data) { int recordId = 0; open(rsName); try { recordId = rs.addRecord(data, 0, data.length); } catch (Exception ex) { ex.printStackTrace(); } return recordId; } /** * 通過key獲取記錄ID * @param rsName * @param key * @return * @throws java.io.IOException */ public int getRecordId(String rsName, String key) throws IOException { int recordId = 0; try { open(rsName); IndexEntry index = new IndexEntry(); int total = rs.getNumRecords(); byte[] data; for (int i = 0; i < total; i++) { data = rs.getRecord(i + 1); ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, data.length); DataInputStream dis = new DataInputStream(bais); //獲取recordId,key index.ReadKey(dis); if (key.equals(index.key)) {//如果讀取的key和傳入的key相同,跳出循環 recordId = index.recordId; dis.close(); bais.close(); break; } } } catch (RecordStoreException ex) { ex.printStackTrace(); } close(); return recordId; } /** * 通過key獲取記錄 * @param rsName * @param key * @return * @throws java.io.IOException */ public byte[] get(String rsName, String key) throws IOException { open(rsName); byte[] data = null; int recordId = getRecordId(StoreHandler.INDEX_RS, key); data = get(rsName, recordId); close(); return data; } /** * 通過記錄ID獲取記錄 * @param rsName * @param recordId * @return */ public byte[] get(String rsName, int recordId) { open(rsName); byte[] data = null; try { data = rs.getRecord(recordId); } catch (RecordStoreException ex) { ex.printStackTrace(); } close(); return data; } }
IStore接口:
package com.org.sunny.rms; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /** * * @author Administrator */ public interface IStore { String getKey(); //存入數據 void SaveData(DataOutputStream output) throws IOException; //獲取數據 void ReadData(DataInputStream input) throws IOException; }
IndexEntry類:
package com.org.sunny.rms; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /** * * @author Administrator */ public class IndexEntry { public int selfId; public int recordId; public String key; public void SaveKey(DataOutputStream output) throws IOException { //注意這裏output是按照順序來寫的,取出來的時候也安裝這種順序來讀 //這樣就能解決一條數據有多列,而又不必去可以添加分隔符 output.writeInt(recordId); output.writeUTF(key); } public void ReadKey(DataInputStream input) throws IOException { recordId = input.readInt(); key = input.readUTF(); } }
User類:
package com.org.sunny.rms; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /** * * @author Administrator */ public class User implements IStore { int id; String name; String sex; int age; String city; String description; public String getKey() { //由於從服務器獲取數據時,每條數據都有一個相應的int類型的主鍵ID(這個是唯一的) //所以我在構造key時根據:類+數據庫的主鍵ID //這樣不僅能夠確保唯一性,而且從key中我就能夠知道這條數據的含義 return "user.info" + id; } //存入數據 public void SaveData(DataOutputStream output) throws IOException { //注意這裏output是按照順序來寫的,取出來的時候也安裝這種順序來讀 //這樣就能解決一條數據有多列,而又不必去可以添加分隔符 output.writeUTF(name); output.writeUTF(sex); output.writeInt(age); output.writeUTF(city); output.writeUTF(description); } //取出數據 public void ReadData(DataInputStream input) throws IOException { name = input.readUTF(); sex = input.readUTF(); age = input.readInt(); city = input.readUTF(); description = input.readUTF(); } }
StoreHandler類(很關鍵的一個類):
package com.org.sunny.rms; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /** * * @author Administrator */ public class StoreHandler { RecordManager rm = new RecordManager(); public static final String INDEX_RS = "index"; public static final String DATA_RS = "data"; /** * 存入數據對應的key * @param index */ public void StoreIndex(IndexEntry index) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); //寫入key index.SaveKey(dos); byte[] key = baos.toByteArray(); String keyName = new String(key); System.out.println("keyName" + keyName); dos.close(); baos.close(); rm.add(INDEX_RS, key); } /** * 存入數據 * @param store * @throws java.io.IOException */ public void StoreData(IStore store) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); //寫入數據 store.SaveData(dos); byte[] data = baos.toByteArray(); int recordId = rm.add(DATA_RS, data); IndexEntry index = new IndexEntry(); index.recordId = recordId; index.key = store.getKey(); //關閉流 dos.close(); baos.close(); //存入唯一的key StoreIndex(index); } /** * 讀取數據 * @param store * @throws java.io.IOException */ public IStore LoadData(IStore store) throws IOException { byte[] data = rm.get(DATA_RS, store.getKey()); ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, data.length); DataInputStream dis = new DataInputStream(bais); //給Store類的各個屬性賦值 store.ReadData(dis); //關閉流 dis.close(); bais.close(); return store; } }