menu

秋梦无痕

一场秋雨无梦痕,春夜清风冻煞人。冬来冷水寒似铁,夏至京北蟑满城。

Avatar

RMS入门

RMS(Record Management System)是MIDP中用来管理MIDlet在persisent介质上的数据存储的记录管理系统。你可以把RMS理解为MIDP上的简单的数据库管理系统。(在MIDP1.0 spec中将RMS描述为"a simple record-oriented database")。在MIDP中关于RMS的API位于javax.microedition.rms包中。
在RMS中,对应数据库的每一个表(table)被称为一个record store,record store中的每一项被称为一个record。可见RMS中数据库的结构是非常简单的。
RecordStore是一个由record组成的文件,具体它如何存储在persisent介质上并保证其完整性是由具体的手机平台来做的。例如重启,换电池后,数据不会失去等等。MIDP1.0 spec中在同一MIDlet suite中的MIDlet创建的RS可以共享,不是同一suite的则不可。到MIDP2.0中不同的Suite就可以共享了,但是其中的访问需要自己控制。一个MIDlet suite中可以创建多个RS。Record store的名字是大小写敏感的,最长32个unicode字符。(也就是32*2byte)。同一MIDlet suite中RS不能重名,如果不同suite则可。
每个RS由record组成,record以字节数组的形式储存。每个record都被给予一个唯一的recordID。recordID以自然数表示,按顺序1,2,3...
MIDP通过RecordStore类来具体实作出record store,可以通过RecordStore.openRecordStore()方法来创建或打开一个record store。
========================================
RecordStore rs;
try{
// determines whether new file is created or not
rs = RecordStore.openRecordStore( "message", true);
}catch(Exception e){
System.out.println("Error opening"+rs_name+":"+e.toString());
}
========================================
openRecordStore()方法在MIDP1.0中的声明如下:
public static RecordStore openRecordStore(String recordStoreName,
boolean createIfNecessary)
第二个参数如果为true,表示如果文件不存在则用给出的文件名新建一个RS,并打开。

Midp 2.0中引入了AuthMode,然后添加了如下openRecordStore()方法:
public static RecordStore openRecordStore(String recordStoreName,
boolean createIfNecessary,
int authmode,
boolean writable)
采用AUTHMODE_PRIVATE模式:只允许调用openRecordStore()的MIDlet访问,相当于调用openRecordStore(recordStoreName, createIfNecessary)方法。
采用AUTHMODE_ANY模式:允许其他MIDlet访问同一个RecordStore,其他MIDlet得到的RecordStore为同一个RecordStore的引用。

public static RecordStore openRecordStore(String recordStoreName,
String vendorName,
String suiteName)
调用其他MIDlet创建的RecordStore。如果RecordStore已经存在,则返回一个引用。如果创建自己的RecordStore,相当于调用openRecordStore(recordStoreName, false)。

然后你可以给record store中添加record:
========================================
String meg1= "Java is nothing.";
byte[] data= meg1.getBytes();
try {
rs.addRecord(data, 0, data.length);
System.out.println("Writing record: " + meg1)
} catch(Exception e){
System.out.println("Error adding record:"+e.toString());
}
========================================
注意:由于RS中的record是以字节数组来保存的,要先把string处理一下。

如果要从已有的record store中读取一个record,也很方便:
========================================
String meg1;
byte[] data;
try {
data = store.getRecord(1);
meg1 = new String(data);
}catch(Exception e){
System.out.println("Error opening record:"+e.toString());
}
========================================

对于RecordStore类常用方法如下

对与record store:
openRecordStore(),closeRecordStore(),deleteRecordStore()

对于record:
addRecord(),getRecord(),deleteRecord(),getNumRecords(),getRecordSize(),

这里只给出了最常用的,还有很多非常有用的方法,具体请参考MIDP API文档。

下面给出一个完整的例程[from ibm.com/developerWorks]:
========================================
import java.util.Vector;
import javax.microedition.rms.*;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class J2meMob extends MIDlet implements CommandListener {
Form mainForm = new Form ("J2MEMobApp");
TextField symbolField = new TextField ("Search By Name", "", 5, TextField.ANY);
StringItem resultItem = new StringItem ("", "");
StringItem resultFName = new StringItem ("", "");
StringItem resultLName = new StringItem ("", "");
StringItem resultAdd = new StringItem ("", "");
StringItem resultPhone = new StringItem ("", "");

RecordStore recStore;
private static final Command okCmd = new Command("OK", Command.OK, 1);

public J2meMob () {
createDatabase();
mainForm.append (symbolField);
mainForm.append (resultItem);
mainForm.append (resultFName);
mainForm.append (resultLName);
mainForm.append (resultAdd);
mainForm.append (resultPhone);
mainForm.addCommand (okCmd);
mainForm.setCommandListener (this);
}

private void createDatabase(){
connect();
populateData();
}

private void connect(){
try {
recStore = RecordStore.openRecordStore("Address", true );
} catch (Exception e) {
resultItem.setLabel ("Error:");
resultItem.setText (e.toString ());
}
}

private void populateData(){
try {
int recordID = 0;
ByteArrayOutputStream bytstream = new ByteArrayOutputStream();
DataOutputStream writer = new DataOutputStream(bytstream);
writer.writeUTF("Leo");
writer.writeUTF("Fernandes");
writer.writeUTF("1500 Dec Road,UC,CA 94545");
writer.writeUTF("5107776666");
writer.flush();

byte[] rec = bytstream.toByteArray();
recordID = recStore.addRecord(rec,0,rec.length);
System.out.println("recordID"+recordID);
writer.flush();
bytstream.reset();

//Second Record
writer.writeUTF("Raj");
writer.writeUTF("Malhotra");
writer.writeUTF("1501 Dec Road,UC,CA 94545");
writer.writeUTF("5107775454");
writer.flush();

rec = bytstream.toByteArray();
recordID = recStore.addRecord(rec,0,rec.length);
System.out.println("recordID"+recordID);
writer.close();
bytstream.close();

recStore.closeRecordStore();
} catch (Exception e) {
resultItem.setLabel ("Error:");
resultItem.setText (e.toString ());
}
}

public void startApp () {
Display.getDisplay (this).setCurrent (mainForm);
}

public void pauseApp () {}

public void destroyApp (boolean unconditional) { }

public void commandAction (Command c, Displayable d) {
try {
// build request string
Vector results = null;
if(c == okCmd){
String symbol = symbolField.getString();
results = fetchData(symbol);
if(results.size() > 0) {
resultFName.setLabel("First Name");
resultFName.setText((String)results.elementAt(0));
resultLName.setLabel("Last Name");
resultLName.setText((String)results.elementAt(1));
resultAdd.setLabel("Address");
resultAdd.setText((String)results.elementAt(2));
resultPhone.setLabel("Phone");
resultPhone.setText((String)results.elementAt(3));
} else {
resultFName.setText("");
resultLName.setText("");
resultAdd.setText("");
resultPhone.setText("");
}
}
} catch (Exception e) {
resultItem.setLabel ("Error:");
resultItem.setText (e.toString ());
}
}

private Vector fetchData(String data){
Vector records = new Vector();
try {
ByteArrayInputStream stream;
DataInputStream reader;
recStore = RecordStore.openRecordStore("Address", true );
String fname;
for (int i = 1; i <= recStore.getNumRecords() && records.size() == 0; i++) {
byte[] rec = new byte[recStore.getRecordSize(i)];
rec = recStore.getRecord(i);
stream = new ByteArrayInputStream(rec);
reader = new DataInputStream(stream);
fname = reader.readUTF();

if(fname.equals(data)){
records.addElement(fname);
records.addElement(reader.readUTF());
records.addElement(reader.readUTF());
records.addElement(reader.readUTF());
}
}
recStore.closeRecordStore();
} catch(Exception e) {
resultItem.setLabel ("Error:");
resultItem.setText (e.toString ());
}
return records;
}

public static void main (String [] argv) {
new J2meMob().startApp ();
}
}
========================================

需要提醒注意的是,当删除了某个记录后,再调用getRecord()方法时会造成InvalidRecordIDException。因为当你删除了记录,比如2时,记录的数目减少了一个,于是调用getNumRecords()会得到2。然而record的id却不会自动发生改变,即还是1,3。再去顺序getRecord()时,会请求一个已经被删除的记录2,从而产生错误。解决的办法需要用到RecordEnumeration类。

难道开始做了?Game platform?

评论已关闭