首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME RMS 記錄管理系統完整指南:從基礎 CRUD 到電話約會簿實戰

     編輯:J2ME

RMS 核心概念

  • RecordStore:持久化存儲單元,名稱 ≤ 32 字元、大小寫敏感、套件內唯一。
  • Record:byte[] + 唯一 recordId(從 1 遞增,刪除後不重用)。
  • 原子性:單次操作保證原子、同步、序列化;多線程需自行同步。
  • 版本/時間戳:每次修改遞增版本號、更新時間戳,供同步引擎使用。

核心 API 速查

// 開啟/建立
RecordStore rs = RecordStore.openRecordStore("MyData", true);

// 寫入
byte[] data = "content".getBytes();
int id = rs.addRecord(data, 0, data.length);

// 讀取
byte[] buf = new byte[rs.getRecordSize(id)];
rs.getRecord(id, buf, 0);
String content = new String(buf, 0, buf.length);

// 更新
rs.setRecord(id, newData, 0, newData.length);

// 刪除
rs.deleteRecord(id);  // id 永久失效

// 關閉
rs.closeRecordStore();

// 刪除整個 Store
RecordStore.deleteRecordStore("MyData");

進階功能:枚舉、排序、過濾

RecordEnumeration:安全遍歷

解決「刪除後 ID 不連續」導致 for (i=1; i<=numRecords; i++) 拋異常的問題:

RecordEnumeration re = rs.enumerateRecords(null, null, false);
while (re.hasNextElement()) {
    byte[] rec = re.nextRecord();        // 取資料
    int id = re.nextRecordId();          // 取 ID(可用於更新/刪除)
}
re.destroy();  // 釋放資源

RecordComparator:自定義排序

class NameComparator implements RecordComparator {
    public int compare(byte[] rec1, byte[] rec2) {
        String s1 = new String(rec1), s2 = new String(rec2);
        int cmp = s1.compareTo(s2);
        return (cmp == 0) ? EQUIVALENT : (cmp < 0 ? PRECEDES : FOLLOWS);
    }
}
// 使用
RecordEnumeration re = rs.enumerateRecords(null, new NameComparator(), false);

RecordFilter:條件查詢

class KeywordFilter implements RecordFilter {
    private String keyword;
    public KeywordFilter(String kw) { keyword = kw.toLowerCase(); }
    public boolean matches(byte[] candidate) {
        return new String(candidate).toLowerCase().indexOf(keyword) >= 0;
    }
}
// 使用
RecordEnumeration re = rs.enumerateRecords(new KeywordFilter("meeting"), null, false);

可組合:enumerateRecords(filter, comparator, false) → 先過濾後排序。

實戰:電話約會簿完整架構

資料格式設計

單條記錄:時間戳(13位)#約會內容 → System.currentTimeMillis() + "#" + desc

刪除標記:"#DELETED#" + 原記錄(保持 ID 不變,避免枚舉亂序)。

核心業務邏輯

// 新增
public void addAppointment(String desc) {
    String rec = System.currentTimeMillis() + "#" + desc;
    rs.addRecord(rec.getBytes(), 0, rec.length());
}

// 列表(跳過已刪除)
public Vector listAppointments() {
    Vector vec = new Vector();
    RecordEnumeration re = rs.enumerateRecords(null, new TimeComparator(), false);
    while (re.hasNextElement()) {
        String s = new String(re.nextRecord());
        if (!s.startsWith("#DELETED#")) vec.addElement(parse(s));
    }
    re.destroy();
    return vec;
}

// 刪除(軟刪除)
public void deleteAppointment(int recordId) {
    byte[] old = rs.getRecord(recordId);
    rs.setRecord(recordId, ("#DELETED#" + new String(old)).getBytes(), 0, old.length);
}

UI 架構(MIDP 高級 UI)

  • WelcomeForm:顯示列表或空狀態,命令:新增、查看、退出
  • MenuForm:List 選單,命令分發
  • AddForm:DateField (日期時間) + TextField (內容) + 保存命令
  • DeleteForm:ChoiceGroup (MULTIPLE) 勾選多條,刪除命令批次軟刪除
  • ItemStateListener:監聽 DateField、TextField、ChoiceGroup 狀態變化,即時更新模型

效能與最佳實踐

場景建議
記錄數 > 500分多個 Store(按月/類別),避免單 Store 索引過大
頻繁查詢建立記憶體索引(ID→關鍵字)輔助 Filter,減少 byte[]→String 轉換
大數據塊 (>8 KB)拆分多條記錄,或改用檔案系統 (JSR 75 FileConnection)
多 MIDlet 共享openRecordStore(name, vendor, suite) 跨套件存取,需簽名權限
備份/遷移導出為 CSV/JSON 上傳伺服器,或 PC 端工具讀取 RMS 檔案

常見坑點

  • 未關閉 Store:closeRecordStore() 必須在 destroyApp() 呼叫,否則資料損壞。
  • 多線程競爭:RMS 操作需 synchronized 或單線程隊列。
  • recordId 假設連續:永遠用枚舉器或 getNextRecordID()。
  • 字串編碼:統一 UTF-8,避免中文亂碼。

結語

RMS 是 J2ME 唯一標準持久化方案,雖無 SQL、無索引,但掌握枚舉器+比較器+過濾器三板斧,配合軟刪除、版本控制、跨套件共享,足以支撐通訊錄、遊戲存檔、離線地圖等中型應用。記住:**資料結構設計決定查詢效能,byte[] 序列化設計決定儲存密度。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved