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

Java me j2me-如何使用RMS存储自定义对象,java-me,rms,Java Me,Rms,在我正在开发的应用程序中,我需要存储客户、产品及其价格的数据。 为了持久保存这些数据,我使用RMS,但知道RMS不支持直接序列化对象,而且因为我读取的数据已经是json格式的,所以我将每个JSONObject存储为其字符串版本,如下所示: rs = RecordStore.openRecordStore(mRecordStoreName, true); JSONArray jsArray = new JSONArray(data);

在我正在开发的应用程序中,我需要存储客户、产品及其价格的数据。 为了持久保存这些数据,我使用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);                  

        }
因此,我有三个记录库(客户、产品和它们的价格),对于每一个记录库,我都按照上面所示进行保存,以保存它们相应的数据

我知道这可能是一个可行的解决方案,但我肯定会有更好的实现。更重要的是,考虑到这三个“表”,我将执行搜索、排序等

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

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

我真的很感谢你的评论和建议

编辑 当您为每个字段定义固定的最大长度时,似乎更容易处理记录。下面是我试过的:

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

 public class Customer {   
        public int idCust;
        public String name;
        public String IDNumber;
        public String address;
    }
        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();
            }
        }
2) 这是我用来将每个jsonObject保存到记录存储的代码:

 public class Customer {   
        public int idCust;
        public String name;
        public String IDNumber;
        public String address;
    }
        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();
            }
        }
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;
    }
这就是我如何实现史密斯先生建议的方法(希望这是他的想法)。然而,我仍然不太确定如何实现搜索


我几乎忘了提到,在我对代码进行这些更改之前,我的记录存储的大小是229048字节,现在它只有158872字节:)

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

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

要帮助您进行序列化/反序列化,可以使用和。使用这些类,您可以在UTF中读/写字符串,它们将为您插入字符串分隔符。但这意味着,当您需要一个字段时,因为您不知道它的确切位置,您必须首先读取该位置的数组

固定长度的优点是,您可以稍后使用,如果您想要检索得分超过10000的玩家的记录,您可以在完全相同的位置查看“点数”字段(从字节数组开始的偏移量为4字节)

所以这是一个折衷。固定长度意味着更快地访问字段(更快的搜索),但可能会浪费空间。可变长度意味着存储空间最小,但搜索速度较慢。什么最适合您的情况将取决于记录的数量和您需要的搜索类型

你在网上有很多教程。仅举几个例子:



首先,非常感谢您抽出时间回答,我非常感谢。现在关于我的应用程序,我最担心的唱片商店是一个存储“产品”的商店,因为它最多可以有1670个项目。(根据
RecordStore.getSize()
)在这个RecordStore上,我必须执行两种搜索:一种是按ProductName搜索,另一种是按ProductID搜索。在这种情况下,您建议采用固定长度还是可变长度?不,只有ProductName是字符串。ID是一个整数。很好。通过这种方式,您可以定义记录结构,其中ID字段位于第一个位置,然后是可变长度字符串字段。诀窍是将字符串放置在每个固定长度字段之后的固定位置。按ID搜索会很快,因为它是一个固定长度的字段,并且是第一个字段。您甚至可以使用
DataInputStream.readInt
来读取它,而不会降低性能。字符串字段的搜索速度也很快,因为尽管长度可变,但您确切地知道它的开始位置。调用
DataInputStream.skipBytes(4)
后,您可以使用
DataInputStream.readUtf
。我刚刚在问题中添加了一些代码,以说明我是如何实现您的建议的。请看一下,我已经看过你的更新了。我认为序列化和反序列化是正确的,但是如果您计划使用第3点中的代码段实现搜索,那么优化记录结构没有任何好处,因为您总是提取所有字段。您应该使用搜索引擎搜索记录,并且只对需要的字段进行反序列化。正是在这种反序列化中,首先拥有ID允许稍微快一点的搜索。