j2me - 如何使用RMS存储自定义对象

时间:2014-06-22 19:10:34

标签: java-me rms

在我开发的应用程序中,我需要存储客户,产品及其价格的数据。 为了保持这些数据我使用RMS,但是知道RMS不直接支持对象序列化,并且由于我读取的数据已经是json格式,我将每个JSONObject存储为其字符串版本,如下所示:

        rs = RecordStore.openRecordStore(mRecordStoreName, true);

        JSONArray jsArray = new JSONArray(data);                        

        for (int i = 0; i < jsArray.length(); i++) {

            JSONObject jsObj = jsArray.getJSONObject(i);
            stringJSON = jsObj.toString();                    
            addRecord(stringJSON, rs);                  

        }

addRecord 方法

public int addRecord(String stringJSON, RecordStore rs) throws JSONException,RecordStoreException {
    int id = -1;           
    byte[] raw = stringJSON.getBytes();
    id= rs.addRecord(raw, 0, raw.length);           
    return id;
}

所以我有三个RecordStores(客户,产品及其价格),每个我都按照上面的说明进行保存以保存相应的数据。

我知道这可能是一种解决方案,但我确信这是一个更好的实施方案。更重要的是,考虑到这三个表&#34;&#34;我将进行搜索,排序等工作。

在这些情况下,在继续搜索或排序之前必须反序列化并不是一个好主意。

这就是我想问你们的原因。根据您的经验,如何在RMS中存储自定义对象,以便以后轻松使用它们?

我非常感谢您的所有意见和建议。

修改

当您为每个字段定义固定的最大长度时,似乎更容易使用记录。所以这就是我的尝试:

1)首先,这是我用来从记录存储中检索值的类:

 public class Customer {   
        public int idCust;
        public String name;
        public String IDNumber;
        public String address;
    }

2)这是我用来将每个jsonObject保存到记录存储的代码:

        RecordStore rs = null;        
        try {
            rs = RecordStore.openRecordStore(mRecordStoreName, true);

            JSONArray js = new JSONArray(data);                           

            for (int i = 0; i < js.length(); i++) {

                JSONObject jsObj = js.getJSONObject(i);                 
                byte[] record = packRecord(jsObj);
                rs.addRecord(record, 0, record.length);

            }


        } finally {
            if (rs != null) {
                rs.closeRecordStore();
            }
        }

packRecord 方法:

       private byte[] packRecord(JSONObject jsonObj) throws IOException, JSONException {
            ByteArrayOutputStream raw = new ByteArrayOutputStream();
            DataOutputStream out = new DataOutputStream(raw);
            out.writeInt(jsonObj.getInt("idCust"));
            out.writeUTF(jsonObj.getString("name"));
            out.writeUTF(jsonObj.getString("IDNumber"));
            out.writeUTF(jsonObj.getString("address"));
            return raw.toByteArray();
        }

3)这是我从记录存储中提取所有记录的方式:

        RecordStore rs = null;
        RecordEnumeration re = null;

        try {
            rs = RecordStore.openRecordStore(mRecordStoreName, true);
            re = rs.enumerateRecords(null, null, false);           
            while (re.hasNextElement()) {
                Customer c;
                int idRecord = re.nextRecordId();
                byte[] record = rs.getRecord(idRecord);
                c = parseRecord(record);
                //Do something with the parsed object (Customer)
            }
        } finally {
            if (re != null) {
                re.destroy();
            }
            if (rs != null) {
                rs.closeRecordStore();
            }
        }

parseRecord 方法:

   private Customer parseRecord(byte[] record) throws IOException {
        Customer cust = new Customer();
        ByteArrayInputStream raw = new ByteArrayInputStream(record);
        DataInputStream in = new DataInputStream(raw);
        cust.idCust = in.readInt();
        cust.name = in.readUTF();
        cust.IDNumber = in.readUTF();
        cust.address = in.readUTF();       
        return cust;
    }

这就是我实施史密斯先生所建议的方式(希望这是他的想法)。但是,我仍然不太确定如何实施搜索。

在我对代码进行更改之前,我几乎忘记提及,我的RecordStore的大小是 229048 字节,现在只有 158872 字节:)< / p>

1 个答案:

答案 0 :(得分:1)

RMS不是那种数据库。您必须将其视为记录集,其中每个记录都是一个字节数组。

因此,当您为记录中的每个字段定义固定的最大长度时,更容易使用它。例如,记录可以是关于游戏中的玩家的一些信息(达到最大级别,得分,玩家姓名等)。您可以将级别字段定义为4个字节长(int),然后将分数字段定义为8个字节(长),然后将名称定义为100个字节的字段(字符串)。这很棘手,因为字符串通常具有可变长度,但您可能希望此字段具有固定的最大长度,并且如果某个字符串比此字符串短,则您将使用字符串终结符char来分隔它。 (这个例子实际上很糟糕,因为字符串是最后一个字段,因此更容易保持它的长度可变。想象一下你有几个连续的字符串类型字段。)

为了帮助您进行序列化/反序列化,您可以使用DataOutputstreamDataInputStream。使用这些类,您可以读取/写入UTF字符串,它们将为您插入字符串分隔符。但这意味着当你需要一个场时,因为你不知道它到底在哪里,你必须先将阵列读到那个位置。

固定长度的优点是您以后可以使用RecordFilter,如果您想要检索分数大于10000的玩家的回忆,您可以查看完全相同的“积分”字段相同的位置(从字节数组开始的4个字节的偏移量)。

所以这是一个权衡。固定长度意味着更快地访问字段(更快的搜索),但可能浪费空间。可变长度意味着最小存储空间但搜索速度较慢对您的案例最有利的将取决于记录的数量和您需要的搜索类型。

你在网上收集了很多教程。仅举几例:

http://developer.samsung.com/java/technical-docs/Java-ME-Record-Management-System
http://developer.nokia.com/community/wiki/Persistent_Data_in_Java_ME