`

J2me中RMS用法

 
阅读更多

RMS(Record Management System)是MIDP中一个非常重要的子系统,因为它是J2ME应用程序进行持久性存储的唯一途径。当然你的系统如果支持JSR75的话,那么你可以使用FileConnection来对文件进行操作,那超出了本文的讨论范围。持久性存储在我们编写应用程序的时候经常要用到,比如纪录游戏的排行榜、记录用户输入的用户名和密码等。本文将主要从RMS的基本概念和使用指南方面进行介绍,目的在于给读者进行一定的指导。

RMS是首先在MIDP1.0中提出的,它所在的包是javax.microedition.rms,在这个包里面总共包括四个接口、一个类和五个异常。由此可见RMS设计的非常小巧,这正是为了满足移动信息设备资源受限的需求。下面我们先弄清楚几个概念。

1. 什么是持久性存储?
持久性存储简单的理解就是数据不因为程序的退出而丢失,一般我们在程序中声明的变量都是存储在stack或者heap上的,程序退出后这些数据会被清除以释放资源。而存储在RMS中的数据是不会被清除的。
2. RMS的数据存储在哪里?
MIDP规范中没有规定RMS的数据必须存储在哪里,而是由厂商来具体实现。一般存储在非挥发性的内存空间。因此这是对程序员透明的。
3. RMS的容量最小为多少?
MIDP中规定厂商实现RMS的时候,提供的存储空间不能小于8KB,例如笔者的Nokia 6108的RMS空间为30KB。
4. RMS中按照Record来存储的,ID是不是等于索引?
ID和索引的区别还是很大的,ID从1开始计数,这和数组的0开始计数有一些不同。ID可以是不连续的,当一个ID标记的Record被删除后那么对应的ID也就变得无效了。ID是不能重复使用的。
5. RMS对存储在其中的数据格式有具体要求吗?
答案是没有,只要数据可以被转换成byte[]那么这个数据就可以存储在RMS中,取出的时候仍然是byte[]。因此这就要求我们开发人员来描绘数据的样子,因为RMS只是负责把数据按照byte[]写入和读出。
6. 在一个MIDlet套件中,RecordStore可以被共享吗?
可以
7. 一个MIDlet套件中的RecordStore可以被另外一个RecordStore访问吗?
在MIDP1.0中不可以,在MIDP2.0中推出了共享机制,通过共享可以实现。

上面以7个问题的形势总结了RMS中需要注意的基本概念,下面我们看看如何使用RMS。一般初学者学习RMS的时候通常会被他们的方法给弄的不知如何下手,因为很多方法看上去很类似。这里我进行如下的总结,提供一些使用指南给大家。

首先读者应该清楚RecordStore就相当于一个数据库,你必须新建一个这样的数据库才可以开始使用RMS进行存储读取数据。新建RecordStore非常简单,可以使用下面的静态方法。

static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary)
注意recordStoreName应该是长度不超过32位的Unicode字符,大小写敏感且在MIDlet套件里面是唯一的,后面的boolean类型的createIfNecessary表示,如果标记为true的时候,那么RecordStore不存在就创建它。关闭RecordStore使用 closeRecordStore()。在RMS中另外一个重要的概念就是Record,这就像数据库中一行一行的数据一样。下面我们首先对 RecordStore中的方法进行区分,有些是用来获得RecordStore信息的有些则是用来获得Record信息的。

1. 获得RecordStore信息
int getVersion()
int getSize()
String getName()
long getLastModified()
2. 获得Record信息
int getNumRecords()
int getNextRecordID()
int getRecordSize(int recordId)

下面讲述如何对Record进行操作,主要包括添加、修改、读取和删除。

1. 读取记录
byte[] getRecord(int recordId)
int getRecord(int recordId, byte[] buffer, int offset)
2. 添加记录
int addRecord(byte[] data, int offset, int numBytes)
3. 更新记录
setRecord(int recordId, byte[] newData, int offset, int numBytes)
4. 删除记录
deleteRecord(int recordId)

前面我们提到了ID和Index是不同的,因为ID可能不连续,那么我们如何来遍历数据呢?很多人可能会想到使用for循环,但是由于id可能不连续,那么这个结果是无法预测的。程序很可能会失败。正是由于这样的原因,在RMS中提供了一个重要的接口RecordEnumeration。它可以遍历 RecordStore中的数据。我们看看下面的方法。

RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated)

在这个方法中还包括了RMS中的另外两个接口RecordFilter和RecordComparator,他们是用来量身定制遍历的结果集的,你可以实现 RecordFilter来决定要把什么样的数据筛选出来,通过实现RecordComparator来决定数据的排序。最后的参数 keepUpdated,如果设置为true的话,那么它会跟踪RecordStore中的数据变化,并且会反映到我们列出的结果集中,要知道这是非常好费资源的操作,建议设置为false。RecordEnumeration相当于一个双向的数据链表。你可以通过调用nextRecordId()和 previousRecordId()来不停的移动。关于RecordEnumeration的其他方法读者可以参考java doc进行学习。

最后一点需要说明的就是共享机制,这是在MIDP2.0中提供的新特性。允许一个套件中的RecordStore被另外一个访问,当然这是要在授权的模式下。

如果MIDlet suite1在创建RecordStore1的时候,授权模式为AUTHMODE_ANY的话,那么其他的套件就有可能访问到RecordStore1,比如上图中的MIDlet suite2。通常这样的访问通过两个步骤来完成。

1. 创建可以被共享的RecordStore
我们可以通过下面的方法来实现,必须要把authmode设置为AUTHMODE_ANY。
static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary, int authmode, boolean writable)

2. 访问RecordStore
如果另外一个MIDlet Suite中的MIDlet想访问的话,那么它需要知道要访问的MIDlet suite的vendorName和suiteName,一般我们可以从jad文件中得到这两个数据。我么使用如下的方法,
static RecordStore openRecordStore(String recordStoreName, String vendorName, String suiteName)


J2ME中RMS的使用解析

在J2ME中,RMS作为唯一的永久性存储工具,其重要性是不言而喻的。但是很多刚刚开始学习J2ME的新人总是抱怨在这方面的资料很少,或者是针对性不强。因此,我想把自己在这方面的一些学习心得和大家交流一下。
RMS即Record Manager System,在手机应用中常常作为得分记录、游戏信息存储等的工具使用。
RMS的使用可以分为两个部分:一、单一记录的构造;二、RecordStore的使用和操作。下面就这两方面进行详细说明。
一、单一记录的构造。我们在存储记录时可能需要记录很多相似的条目,在这里我们可以把这种结构看成数据库,我们在这一步就是要构造数据库中的一行,即单一记录的构造。程序的源码如下:
package com.cuilichen.usual;

import java.io.ByteArrayInputStream;//要使用到的各种输入输出流
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Appointment {//单一记录的类名
private int int1; //
private int int2; //
private long long1;
private String str1; //str1作为保留字段,记录检索的关键字
private String str2; //
private String str3; //
private boolean WroteFlag; //

public Appointment() {
}

public Appointment(int _int1, int _int2, long _long1, String _str1,
String _str2, String _str3, boolean _WroteFlag) {
this.int1 = _int1; //写入RMS的构造函数
this.int2 = _int2;
this.long1 = _long1;
this.str1 = _str1;
this.str2 = _str2;
this.str3 = _str3;
this.WroteFlag = _WroteFlag;
}

public Appointment(byte[] rec) {
initAppointmnet(rec); //读取RMS内容的构造函数
}

public byte[] toBytes() { //写成字节

byte[] data = null;

try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(int1);
dos.writeInt(int2);
dos.writeLong(long1);
dos.writeUTF(str1);
dos.writeUTF(str2);
dos.writeUTF(str3);
dos.writeBoolean(WroteFlag);
data = baos.toByteArray();
baos.close();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}

public void initAppointmnet(byte[] rec) { //从字节读取内容

ByteArrayInputStream bais = new ByteArrayInputStream(rec);
DataInputStream dis = new DataInputStream(bais);

try {
int1 = dis.readInt();
int2 = dis.readInt();
long1 = dis.readLong();
str1 = dis.readUTF();
str2 = dis.readUTF();
str3 = dis.readUTF();
WroteFlag = dis.readBoolean();
} catch (Exception e) {
e.printStackTrace();
}
}

public int getInt1() { //int
return int1;
}
public int getInt2() {
return int2;
}
public long getLong1() {
return long1;
}

public String getStr1() { //String
return str1;
}

public String getStr2() { //String
return str2;
}

public String getStr3() {
return str3;
}

public boolean getWroteFlag() { //返回写入标志
return WroteFlag;
}
}
这个类的使用保证了我们在使用流时,内容的写入和输出。当然,就如同数据库表的设计一样,我们可以任意对每一条记录增加或减少字段,在上面的类中我只使用了int1,int2,long1,str1,str2,str3和WroteFlag一共7个字段


二、RecordStore的操作。类RMS如下:
package com.cuilichen.usual;

import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;

public class RMS {
public static final int Int1 = 0;//各个字段的默认数值
public static final int Int2 = 0;
public static final long Long1 = 0;
public static final String Str1 = "";
public static final String Str2 = "";
public static final String Str3 = "";

public static boolean addRecord(String name, int int1, int int2,//添加记录
long long1, String str1, String str2, String str3, boolean b) {
boolean success = false;

try {
RecordStore rs = RecordStore.openRecordStore(name, true);
Appointment app = new Appointment(int1, int2, long1, str1, str2,str3, b);
//既然str1作为保留字段,我们在这里就要如此操作:例如int1为我们设定的关键字,那么str1 = Integer.toString(int1);
byte[] data = app.toBytes();
rs.addRecord(data, 0, data.length);
rs.closeRecordStore();
success = true;
} catch (Exception e) {
e.printStackTrace();
}
return success;
}
public static int getNumOfRecords(String name) {//得到RMS中记录的条数
try {
RecordStore rs = RecordStore.openRecordStore(name, true);

return rs.getNumRecords();
} catch (Exception e) {
return 0;
}
}

public static Appointment[] getRecords(String name) {//取得RMS中的所有记录
Appointment[] result = { };

try {
RecordStore rs = RecordStore.openRecordStore(name, false);
RecordEnumeration re = rs.enumerateRecords(null, null, false);
result = new Appointment[rs.getNumRecords()];

for (int i = 0; i < result.length; i++) {
int j = re.previousRecordId();
Appointment app = new Appointment(rs.getRecord(j));
result[i] = app;

//System.out.println("app["+i+"] "+app.getStr2());
}

rs.closeRecordStore();
} catch (Exception e) {
}

return result;
}

public static Appointment getRecord(String name, int j) {//根据记录编号(参数 int j)取得一条记录
Appointment result = new Appointment();

try {
RecordStore rs = RecordStore.openRecordStore(name, false);
RecordEnumeration re = rs.enumerateRecords(null, null, false);
result = new Appointment(rs.getRecord(j));
rs.closeRecordStore();
} catch (Exception e) {
}

return result;
}

public static int getIndex(String name, String content) {//得到记录号int j,这里需要使用保留字段str1
RecordStore rs = null;
RecordEnumeration re = null;

try {
rs = RecordStore.openRecordStore(name, false); //open
re = rs.enumerateRecords(null, null, false); //enumeration

for (int i = 0; i < RMS.getNumOfRecords(name); i++) {
int j = re.nextRecordId();
Appointment app = new Appointment(rs.getRecord(j));

if (app.getStr1().equals(content)) {

return j;
}
}
} catch (Exception e) {
}
return 1;
}

public static boolean setRecord(String name, int id, int int1, int int2,//设置记录号为id的记录
long long1, String str1, String str2, String str3, boolean b) {
boolean success = false;
RecordStore rs = null;
RecordEnumeration re = null;

try {
rs = RecordStore.openRecordStore(name, false); //open
re = rs.enumerateRecords(null, null, false); //enumeration

Appointment app = new Appointment(int1, int2, long1, str1, str2, str3, b);
//str1作为保留字段,在这里如此操作:例如若int1为我们设定的关键字,那么str1 = Integer.toString(int1);

byte[] data = app.toBytes();
rs.setRecord(id, data, 0, data.length);
success = true;
rs.closeRecordStore();
} catch (Exception e) {
}

return success;
}
}
在这个类中,我没有将各个Exception向外抛出,一般来说这样作是不合适的,它违背了Java的异常处理机制。但是在我使用这个类的各个J2ME程序中,它是可以胜任的,所以也就没有进行进一步的修改。
有了以上的两个类和你对RMS的理解,在程序中,你就可以顺畅的使用RMS了。
比如在MIDlet开始时,如下操作(增加记录):
protected void startApp() throws MIDletStateChangeException {
if (RMS.getNumOfRecords(rsName) = = 0) {//rsName在前面已经声明了。String rsName=“MyRMS”;
for (int i = 0; i <6; i++) {
RMS.addRecord(rsName, RMS.Int1, i, RMS.Long1, Integer . toString(i), RMS.Str2, "1234567890123456789",false);
}
}

分享到:
评论

相关推荐

    自己写的j2me—rms引擎写的电话本

    在本文中,我们将深入探讨如何使用Java 2 Micro Edition(J2ME)平台中的Record Management System(RMS)引擎来创建一个简单的电话本应用。这个应用涵盖了基础的联系人管理功能,包括添加、查询、显示所有联系人、...

    J2ME 之RMS 很基础很全面

    在J2ME中,RMS(Record Management System)是一个小型的数据库管理系统,专门设计用于在资源有限的设备如手机上进行数据存储和持久化。RMS提供了简单且高效的数据管理方式,适用于那些无法使用全功能数据库系统的...

    J2ME中RMS存储工具使用解析

    总结来说,RMS是J2ME中存储数据的重要工具,通过理解单一记录的构造以及RecordStore的操作,开发者能够有效地管理应用程序的数据存储,实现游戏状态的保存、用户数据的持久化等功能。正确地使用RMS是开发J2ME应用不...

    J2me数据库引擎类.rar_j2me_rms

    标题中的"J2me数据库引擎类.rar_j2me_rms"暗示了这是一个关于使用J2ME RMS实现的轻量级数据库引擎。这个压缩包可能包含了一个或多个Java类,用于封装RMS操作,简化开发者对RMS的使用。 描述中的“一个用J2me 的RMS ...

    关于J2ME中RMS的使用解析

    在J2ME(Java Micro Edition)平台上,RMS(Record Manager System)是开发者用来实现持久化数据存储的主要机制。RMS 提供了一种简单的方法来存储和检索应用程序所需的数据,尤其是在资源有限的移动设备上。它类似于...

    J2ME_rms数据存储详解

    在Java Micro Edition (J2ME) 平台中,Resource Management System (RMS) 是一种用于存储应用程序数据的重要机制。由于J2ME主要用于资源有限的移动设备,如手机和掌上电脑,RMS提供了一种高效且灵活的数据存储解决...

    J2ME的RMS增删改查的简单事例

    在这个“J2ME的RMS增删改查的简单事例”中,我们将深入探讨如何在J2ME应用中使用Record Management System(RMS)来实现电话簿功能,包括添加联系人、删除联系人、修改联系人信息以及查询联系人。 1. **Record ...

    J2ME_RMS实例_手机电话本

    在J2ME中,RMS(Record Management System)是用于存储应用程序数据的一种机制,尤其适合在内存有限且没有持久化数据库的设备上使用。本文将深入探讨如何在J2ME平台上利用RMS实现一个手机电话本实例,包括记录的增、...

    j2me_rmsj2me_rms

    RMS (Record Management System) 是 J2ME 中的一个核心部分,它提供了一种在移动设备上存储数据的方法。在本文中,我们将深入探讨 J2ME RMS 的相关知识点。 1. **RMS 概述**:RMS 是 J2ME 为资源有限的设备设计的...

    j2me RMS记录管理系统 备忘录

    在本文中,我们将深入探讨基于J2ME的RMS(Record Management System)记录管理系统,特别关注如何在S60及更高版本的移动设备上实现一个备忘录应用。这个系统对于初学者来说是一个很好的学习资源,因为它展示了如何...

    J2ME RMS 小试牛刀

    本文将深入探讨J2ME RMS的基本概念、使用方法以及一些实际应用示例。 **RMS简介** RMS是J2ME MIDP(Mobile Information Device Profile)的一部分,它提供了一种本地数据存储方案,允许应用程序在手机上保存用户...

    J2ME RMS 封装

    在移动设备或嵌入式系统中,由于资源限制,无法像Java SE或Android那样使用完整的数据库系统,因此J2ME引入了RMS来处理本地数据存储。RMS提供了一套简单的API,允许开发者创建、读取、更新和删除数据记录。 **RMS的...

    J2ME 记录管理存储

    在J2ME(Java 2 Micro Edition)的开发环境中,记录管理存储(Record Management System,简称RMS)扮演着关键角色,它为MIDlet应用程序提供了数据持久化存储的能力。MIDlet,即移动信息设备上的小型应用,依赖于RMS...

    j2me RMS Demo

    这个“j2me RMS Demo”是一个针对初学者的实例,旨在帮助他们理解并掌握如何在J2ME应用程序中有效地使用RMS系统。 RMS是Java ME为资源有限的移动设备提供的一种轻量级数据库解决方案,它允许开发者创建自定义的数据...

    郭克华J2ME实例教程完整版之RMS编程1

    通过学习郭克华的J2ME实例教程,开发者不仅可以掌握RMS的基本用法,还能了解到如何将这些知识应用于实际项目中,解决移动设备上的数据管理问题。教程中的“15wancheng.wmv”很可能是一个完整的示例,演示了RMS编程的...

    RMS的使用解析

    因此,本文将详细介绍RMS的基本概念以及具体的使用方法,希望能够帮助到正在学习J2ME的开发者们。 #### 二、RMS的具体使用 RMS的使用主要可以分为两个方面:单一记录的构造以及RecordStore的使用和操作。 ##### 1...

    用j2me写的电话簿程序,利用rms存储联系人信息

    本文将深入探讨如何使用J2ME编写一个简单的电话簿程序,并重点讲解如何利用Record Management System (RMS)来持久化存储联系人信息。 首先,J2ME是Java平台的一个子集,主要设计用于嵌入式系统和移动设备,如手机和...

    J2me保存记录框架(封装RMS)

    在 J2ME 中,Record Management System (RMS) 是一个内置的数据存储机制,用于在没有持久化数据库支持的情况下保存应用程序的数据。下面将详细介绍如何使用 RMS 框架来保存记录以及封装 RMS 类的方法。 1. **RMS ...

    J2ME中文教程(包含代码)

    通过这个J2ME中文教程,开发者不仅可以学习到J2ME的基本概念和使用方法,还能通过实际的代码示例深化理解和提升技能。无论你是初学者还是有一定经验的开发者,都可以从这个教程中受益匪浅,为你的移动应用开发之路...

Global site tag (gtag.js) - Google Analytics