分享
 
 
 

Record Management System从入门到精通系列之一

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

Record Management System是J2ME的一个重要的子系统,目的是实现应用程序本地数据的持久性存储。目前支持文件系统的移动信息设备还有限,因此Record Management System是J2ME开发人员实现本地数据存储的首选途径。本文的目的就是全面的介绍Record Management System的知识。

顾名思义Record Management System是管理数据的系统,Record是系统中最重要的实体。在移动设备存储空间存储的并不是字段,而是字节数组。Mobile Infomation Device Profile(MIDP)规范中并没有规定什么样的数据才能存储为记录,事实上记录是任何可以被字节数组表示的数据,例如图片、文本等。Record Management System的职责是存储和唯一标识记录,而表示数据的任务是由应用程序来完成的,因此J2ME的开发人员往往要花费更多的精力来处理存储空间中的数据。这样做的目的是简化MIDP的实现,使得J2ME的子系统尽量的小巧、灵活。毕竟移动信息设备的存储空间和处理器的能力都有限。

Record Store是一系列记录的有序集合,记录是不能单独存在的,必须属于Record Store。Record Store保证记录的读写操作都是原子的,数据不会被破坏。在API中Record Store是由javax.microedition.rms.RecordStore实现的,关于RecordStore的具体操作在接下来的文章中会有详细的介绍。

MIDP规范中说明移动信息设备要提供至少8K的非易失性存储空间给应用程序来实现数据的持久性存储。但是不同的设备提供的空间并不相同。如果MIDlet suite使用了Record Management System,那么它必须在MANIFEST文件和JAD文件中通过设置MIDlet-Data-Size来说明它所需要的最小的数据存储空间,单位是字节,例如MIDlet-Data-Size:8192。如果你的值超过了移动设备规定的最大值那么你的应用程序将不能正确安装。这个值并不是移动设备真正提供给应用程序的最大Record Management System的存储空间,往往要大一些,因此开发人员应该避免把应用程序需要的最小存储空间设置的过大,必要的时候应该参考相关设备的说明手册。在非易失性存储空间内读写数据往往速度会比较慢,因此针对频繁访问的数据最好提供缓存的机制来提供性能。Record Management System的读写操作是线程安全的,但是由于Record Store是被整个MIDlet suite共享的,所以如果不同MIDlet上运行的线程操作Record Store的时候,我们应该进行必要的线程同步,避免数据被破坏。

MIDP1.0和MIDP2.0中关于Record Management System的实现有些不同,在同一个MIDlet suite里面的MIDlets可以相互访问彼此的Record Store。但是在MIDP1.0的实现中,并没有提供在不同MIDlet suite之间共享Record Store的机制。在MIDP2.0中提供的了新的API来解决不同MIDlet suite之间共享Record Store的问题,在创建Record Store的时候通过授权模式和读写控制参数来进行共享机制的管理,我将在下篇文章中进行详细的介绍。

加强对Record Management System的理解的最好的办法就是进行实际的开发,在进行开发中我发现并不是所有移动设备的MIDP实现都准确无误。当我用getSizeAvaliable()方法查询Nokia6108的可用Record Store空间的时候得到的数值是超过1M字节,但是当我写入40K的数据的时候就出现了RecordStoreFullException异常,因此我编写了一个自动测试手机Record Store最大存储空间的软件。原理是每隔一定时间例如100-500毫秒向Record Store内写入1K字节的数据,当抛出存储空间已满的异常的时候就可以得到最大值了,精确单位为K字节。下面是程序的源代码和JAD文件的内容,开发平台为Eclipse3.0RC2+EclipseME0.4.1+Wtk2.1+J2SDK1.4.2._03,在真机Nokia 6108上测试通过并显示最大值为31K。(请不要在模拟器上进行测试,那样结果没有意义)

总结:本文只是带领读者对Record Management System进行了大概的了解,虽然在文章最后提供了一个应用程序。但是并没有深入分析如何使用Record Management System。在接下来的文章中我们会深入分析javax.microedition.rms包中的类,重点是如何使用RecordStore类。

//RMSAnalyzer.java

import javax.microedition.lcdui.Alert;

import javax.microedition.lcdui.AlertType;

import javax.microedition.lcdui.Display;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

import javax.microedition.rms.RecordStoreException;

/*

* Created on 2004-6-21

*

* TODO To change the template for this generated file go to

* Window - Preferences - Java - Code Style - Code Templates

*/

/**

* @author ming

*

* TODO To change the template for this generated type comment go to Window -

* Preferences - Java - Code Style - Code Templates

*/

public class RMSAnalyzer extends MIDlet

{

private Display display;

private CounterCanvas counterCanvas;

private Alert alert;

/*

* (non-Javadoc)

*

* @see javax.microedition.midlet.MIDlet#startApp()

*/

protected void startApp() throws MIDletStateChangeException

{

// TODO Auto-generated method stub

display = Display.getDisplay(RMSAnalyzer.this);

alert = new Alert("错误提示");

try

{

String interval = this.getAppProperty("INTER");

int t = Integer.parseInt(interval);

counterCanvas = new CounterCanvas(t, 1, this);

}

catch (RecordStoreException e)

{

this.showAlertError(e.getMessage());

}

display.setCurrent(counterCanvas);

}

public Display getDisplay()

{

return display;

}

/*

* (non-Javadoc)

*

* @see javax.microedition.midlet.MIDlet#pauseApp()

*/

protected void pauseApp()

{

// TODO Auto-generated method stub

}

/*

* (non-Javadoc)

*

* @see javax.microedition.midlet.MIDlet#destroyApp(boolean)

*/

protected void destroyApp(boolean arg0) throws MIDletStateChangeException

{

// TODO Auto-generated method stub

}

public void showAlertError(String message)

{

alert.setString(message);

alert.setType(AlertType.ERROR);

alert.setTimeout(3000);

display.setCurrent(alert);

}

}

//CounterCanvas.java

import java.util.Timer;

import java.util.TimerTask;

import javax.microedition.lcdui.Canvas;

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Graphics;

import javax.microedition.midlet.MIDletStateChangeException;

import javax.microedition.rms.*;

/*

* Created on 2004-6-21

*

* TODO To change the template for this generated file go to

* Window - Preferences - Java - Code Style - Code Templates

*/

/**

* @author ming

*

* TODO To change the template for this generated type comment go to Window -

* Preferences - Java - Code Style - Code Templates

*/

public class CounterCanvas extends Canvas implements CommandListener

{

private RMSModel model;

private RMSAnalyzer RMSanalyzer;

private int interTime;

private int counter;

private boolean go = true;

public static Command backCommand = new Command("退出", Command.EXIT, 3);

public static final int INC = 1;

public final Timer timer = new Timer();

public CounterCanvas(int interTime, int base, RMSAnalyzer rmsa)

throws RecordStoreException

{

this.interTime = interTime;

this.counter = base;

this.RMSanalyzer = rmsa;

model = new RMSModel(base, RMSanalyzer);

this.addCommand(backCommand);

this.setCommandListener(this);

TimerTask timerTask = new TimerTask()

{

public void run()

{

try

{

model.writeRecord(INC);

counter++;

} catch (RecordStoreFullException e)

{

go = false;

model.deleteRMS();

timer.cancel();

} catch (RecordStoreException e)

{

model.deleteRMS();

RMSanalyzer.showAlertError(e.getMessage());

timer.cancel();

}

repaint();

}

};

timer.schedule(timerTask, 1000, interTime);

}

/**

* @param counter

* The counter to set.

*/

public void setCounter(int counter)

{

this.counter = counter;

}

/**

* @param interTime

* The interTime to set.

*/

public void setInterTime(int interTime)

{

this.interTime = interTime;

}

/*

* (non-Javadoc)

*

* @see javax.microedition.lcdui.Displayable#paint(javax.microedition.lcdui.Graphics)

*/

protected void paint(Graphics arg0)

{

// TODO Auto-generated method stub

int SCREEN_WIDTH = this.getWidth();

int SCREEN_HEIGHT = this.getHeight();

arg0.drawRect(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 2,

SCREEN_WIDTH * 4 / 5, 10);

if(RMSanalyzer.getDisplay().isColor())

{

arg0.setColor(128, 128, 255);

}

arg0.fillRect(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 2, counter, 10);

if (!go)

arg0.drawString("最大值:" + counter+"K字节", 0, 0, Graphics.TOP

| Graphics.LEFT);

}

/*

* (non-Javadoc)

*

* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command,

* javax.microedition.lcdui.Displayable)

*/

public void commandAction(Command arg0, Displayable arg1)

{

// TODO Auto-generated method stub

if (arg0 == backCommand)

{

try

{

model.deleteRMS();

RMSanalyzer.destroyApp(false);

RMSanalyzer.notifyDestroyed();

} catch (MIDletStateChangeException e)

{

}

}

}

}

//RMSModel.java

import javax.microedition.rms.*;

/**

* @author ming

*

* TODO To change the template for this generated type comment go to Window -

* Preferences - Java - Code Style - Code Templates

*/

public class RMSModel

{

public static final int K = 1024;

private RecordStore rs;

private int baseCount;

private RMSAnalyzer RMSanalyzer;

public static final String name = "test";

public RMSModel(int baseCount, RMSAnalyzer rmsa)

throws RecordStoreException

{

this.baseCount = baseCount;

this.RMSanalyzer = rmsa;

if (rs == null)

{

rs = RecordStore.openRecordStore(name, true);

writeRecord(baseCount);

}

}

public void writeRecord(int count) throws RecordStoreException

{

byte[] data = new byte[count * K];

for (int i = 0; i < count; i++)

{

data[i] = 1;

}

rs.addRecord(data, 0, count * K);

}

public void deleteRMS()

{

try

{

rs.closeRecordStore();

RecordStore.deleteRecordStore(name);

} catch (RecordStoreException e)

{

RMSanalyzer.showAlertError(e.getMessage());

}

}

}

RMSAnalyzer.jad

MIDlet-Jar-Size: 5293

MIDlet-1: RMSAnalyzer,,RMSAnalyzer

MIDlet-Jar-URL: RMSAnalyzer.jar

MicroEdition-Configuration: CLDC-1.0

MIDlet-Version: 1.0.0

MIDlet-Name: RMSAnalyzer

MIDlet-Data-Size: 8192

MIDlet-Vendor: Midlet Suite Vendor

MicroEdition-Profile: MIDP-1.0

INTER: 100

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有