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

打造自訂 RMS 框架:以字串鍵值替代整數 RecordID 的靈活儲存方案

     編輯:關於.NET

前言:J2ME RMS 的限制

J2ME Record Management System (RMS) 僅支援以整數 RecordID 存取記錄,且枚舉查詢效率極低 (需逐筆比對位元組陣列)。應用層往往需要以有意義的字串鍵 (如 "sys.settings"、"user.info_123") 存取資料,並支援多型別物件儲存。本文實作一個 StorageHandler 框架,引入索引機制實現字串鍵值查詢。

架構設計

核心類別圖

  • RecordManager:RMS 底層操作封裝 (開啟/關閉/增刪改查 RecordStore)
  • StoreHandler:框架進入點,提供 StoreData、LoadData、StoreIndex 高階 API
  • IndexEntry:索引實體,包含 selfId、recordId (指向資料 RecordStore)、key (字串鍵值)
  • IStore:序列化介面,定義 SaveData、ReadData、getKey,業務物件實作此介面即可納管
  • User、Person:業務實體範例,實作 IStore

RMS 索引機制示意圖

類別結構圖

兩個 RecordStore 分工

RecordStore 名稱用途記錄內容
index索引表IndexEntry 序列化資料 (recordId + key)
data實際資料業務物件序列化位元組陣列

查詢流程:三步驟

  1. 在 index RecordStore 中逐筆讀取 IndexEntry,比對 key 找到目標
  2. 取得對應的 recordId
  3. 以 recordId 從 data RecordStore 直接讀取記錄

核心代碼實作 (Java ME)

RecordManager — 底層 RMS 操作


public class RecordManager {
    private RecordStore rs;
    private boolean isOpen = false;

    public void open(String rsName) {
        rs = RecordStore.openRecordStore(rsName, true, RecordStore.AUTHMODE_ANY, true);
    }

    public void close() { rs.closeRecordStore(); }

    public int add(String rsName, byte[] data) {
        open(rsName);
        int recordId = rs.addRecord(data, 0, data.length);
        close();
        return recordId;
    }

    public byte[] get(String rsName, int recordId) {
        open(rsName);
        byte[] data = rs.getRecord(recordId);
        close();
        return data;
    }

    public int getRecordId(String rsName, String key) throws IOException {
        open(rsName);
        int total = rs.getNumRecords();
        for (int i = 1; i <= total; i++) {
            byte[] data = rs.getRecord(i);
            IndexEntry index = new IndexEntry();
            index.ReadKey(new DataInputStream(new ByteArrayInputStream(data)));
            if (key.equals(index.key)) {
                close();
                return index.recordId;
            }
        }
        close();
        return 0;
    }
}

IStore — 序列化契約


public interface IStore {
    String getKey();                    // 唯一鍵值,如 "user.info_123"
    void SaveData(DataOutputStream out) throws IOException;
    void ReadData(DataInputStream in) throws IOException;
}

IndexEntry — 索引實體


public class IndexEntry {
    public int selfId;
    public int recordId;
    public String key;

    public void SaveKey(DataOutputStream out) throws IOException {
        out.writeInt(recordId);
        out.writeUTF(key);  // 寫入順序固定,讀取時同序
    }

    public void ReadKey(DataInputStream in) throws IOException {
        recordId = in.readInt();
        key = in.readUTF();
    }
}

User — 業務實體範例


public class User implements IStore {
    public int id;
    public String name, sex, city, description;
    public int age;

    public String getKey() {
        return "user.info" + id;  // 類別前綴 + 業務主鍵,確保唯一且可讀
    }

    public void SaveData(DataOutputStream out) throws IOException {
        out.writeUTF(name);
        out.writeUTF(sex);
        out.writeInt(age);
        out.writeUTF(city);
        out.writeUTF(description);
    }

    public void ReadData(DataInputStream in) throws IOException {
        name = in.readUTF();
        sex = in.readUTF();
        age = in.readInt();
        city = in.readUTF();
        description = in.readUTF();
    }
}

StoreHandler — 核心協調器


public class StoreHandler {
    private RecordManager rm = new RecordManager();
    public static final String INDEX_RS = "index";
    public static final String DATA_RS = "data";

    public void StoreIndex(IndexEntry index) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        index.SaveKey(dos);
        rm.add(INDEX_RS, baos.toByteArray());
        dos.close(); baos.close();
    }

    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();
        StoreIndex(index);

        dos.close(); baos.close();
    }

    public IStore LoadData(IStore store) throws IOException {
        byte[] data = rm.get(DATA_RS, store.getKey());
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bais);
        store.ReadData(dis);
        dis.close(); bais.close();
        return store;
    }
}

測試畫面與結果

SaveForm 介面

ReadForm 介面

測試結果

框架優勢總結

  • 語意化鍵值:以 "user.info_123" 替代無意義整數 ID,業務邏輯清晰
  • 型別解耦:業務類別僅實作 IStore,零 RMS 相依
  • 索引加速:避免全表掃描資料 RecordStore,僅掃描較小的索引表
  • 擴展性:新增實體類別只需實作 IStore,無需修改框架代碼
  • 序列化可控:DataOutputStream 寫入順序即讀取順序,無需分隔符號

潛在改進方向

  • 索引快取:將 index 載入記憶體 Hashtable,查詢 O(1)
  • 批次操作:支援 StoreData(List<IStore>) 減少 RMS 開關開銷
  • 異動通知:資料變更時觸發事件,支援 UI 即時更新
  • 加密儲存:敏感資料 (密碼、Token) 在 SaveData 中加密

結語

在受限的 J2ME RMS 環境下,引入索引層與介面契約,即可構建出具備字串鍵值存取、型別安全、擴展性良好的輕量儲存框架。此設計模式同樣適用於其他簡易鍵值儲存系統 (如 Android SharedPreferences、嵌入式檔案系統) 的進階封裝。

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