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

原创 2004年06月23日 00:36:00

      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

 

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

      Record Management System是J2ME的一个重要的子系统,目的是实现应用程序本地数据的持久性存储。目前支持文件系统的移动信息设备还有限,因此Record Managem...
  • mingjava
  • mingjava
  • 2004年06月23日 00:36
  • 6008

RMS (Rights Management Services)基于SDK2.1的二次开发环境搭建

概述 AD RMS 由服务器和客户端组件组成。服务器安装可参考微软官网指南,本文侧重描述客户端安装和开发环境配置。 客户端组件可以在客户端或服务器操作系统上运行,包含使应用程序可以加密和解密内容、检...
  • qq_33336155
  • qq_33336155
  • 2016年11月07日 15:53
  • 731

WF从入门到精通系列

WF从入门到精通系列
  • tigerzx
  • tigerzx
  • 2017年03月11日 12:47
  • 163

Windows 2008从入门到精通系列教程(一)

Windows Server 2008从入门到精通系列教程(一)             自我庆祝一下,荣幸的获得了微软最有价值专家,感谢51CTO这个平台,感谢各位朋友对我的支持和厚爱。以后我...
  • pmpgao
  • pmpgao
  • 2014年11月12日 15:54
  • 721

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

   前面两篇文章详细的介绍了Record Management System的基本概念以及对象序列化的问题,现在我们主要介绍关于RecordStore类的使用,在SUN的网站提供了一个RMSAnal...
  • mingjava
  • mingjava
  • 2004年06月25日 23:38
  • 2905

RMS管理数据的系统

  • 2007年12月20日 20:04
  • 47KB
  • 下载

ActiveMQ从入门到精通(三)

这是ActiveMQ系列的最后一篇文章,主要是关于ActiveMQ集群,这里采用的方式是:Zookeeper+LevelDB+ActiveMQ。前面2篇博客地址如下:《ActiveMQ从入门到精通(一...
  • jek123456
  • jek123456
  • 2017年05月19日 09:36
  • 647

nginx从入门到精通And原理

本文是多篇文章整理在一起,因为本人比较懒。。。so整理了下各位大牛的文章便于我自己以及后来者一步到位的学习。 文章中的一些内容转载至: http://geek.csdn.net/news/detai...
  • woshishuiaaaD
  • woshishuiaaaD
  • 2016年12月08日 10:36
  • 827

小议:Information Rights Management 无法连接RMS Server解决方案

今天在指导学员部署SharePoint2013 Information Rights Management与Windows Server2012 AD RMS结合时遇到一个错误,配置完Window...
  • ShelleyLiu0415
  • ShelleyLiu0415
  • 2015年09月22日 17:17
  • 1177

【IPTV】Hybrid Video解决方案概念与价值

个人的理解:华为hybrid video 平台是想打造一个机遇video领域通用的一个平台,自适应于传统TV ,IPTV ,OTT这三个电信最主要的业务。主要是IPTV业务为主。 兼或OTT(视频流媒...
  • datamining2005
  • datamining2005
  • 2017年04月01日 10:54
  • 795
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Record Management System从入门到精通系列之一
举报原因:
原因补充:

(最多只允许输入30个字)