打造自己的RMS框架(三)

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存儲記錄。
20051106230237687

我爲我的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。
1 2 3

源代碼下載地址:http://download.csdn.net/source/1932733

發佈了52 篇原創文章 · 獲贊 0 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章