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;
}
}
下面是我進行測試的界面和結果:
一個SaveForm,一個ReadForm。