Home UC3M
Home IT

RMS: Almacenamiento en MIDP

 OBJETIVOS


MIDP define una sencilla base de datos orientada a registros que permite almacenar a las aplicaciones datos de forma persistente. Esta base se denomina Record Management System (RMS).
La práctica de hoy tiene como objetivo aprender los conceptos básicos para el manejo de esta base datos, a través del API que nos ofrece MIDP. Todas las clases relacionadas con RMS están contenidas en el paquete javax.microedition.rms.
Esta práctica os debe servir para enfrentaros con dos partes de la práctica final: almacenar el estado de una partida, para que sea posible parar y reanudar un partida (opciones del menú Stop y Restart) y para mantener el registro de mejores puntuaciones (opción Records).

 RecordStore


El mecanismo básico de almacenamiento de RMS es denominado record store. Un record store es un conjunto de registros, y un registro es un byte array de datos de tamaño variable. Un record store está representado por un objeto de la clase RecordStore.
Existen reglas importantes sobre los record store:
  1. El nombre de un record store consiste en una combinación de hasta 32 caracteres (sensible a las mayúsculas).

  2. Los record stores creados por MIDlets de un mismo MIDlet suite están almacenados en el mismo espacio de nombres, y por lo tanto, pueden compartir y ver sus contenidos.

  3. Los record stores creados por MIDlets en un MIDlet suite, no son accesibles para los MIDltes de otros MIDlets suite.

  4. El nombre de un record store debe ser único en un MIDlet suite.


Operaciones con un Record Store

La clase RecordStore proporciona los siguientes métodos para crear, abrir, cerrar y borrar un record store:
Cada record store mantiene al menos un campo de cabecera. Si no existe espacio suficente para almacenar la cabecera, el record store no se creará y se producirá una RecordStoreFullException. Si ocurre otro tipo de problema, como que el nombre del record store es demasiado largo, o el record store está corrupto, se produce una RecordStoreException.

A continuación, se puede ver un sencillo ejemplo de creación de un RecordStore (RecordStoreTest1.java).

import javax.microedition.midlet.*;
import javax.microedition.rms.*;

public class RecordStoreTest1 extends MIDlet {
    public RecordStoreTest1() {	
    }
    public void startApp() throws MIDletStateChangeException {
        RecordStore rs=null;
        try {
	    rs = RecordStore.openRecordStore("file1",true);
            System.out.println("record store file1 is opened.");
        }catch(Exception e){
            System.out.println("Error: "+e.getMessage());
        }
        finally{
            //close the record store
            try {
	        rs.closeRecordStore();
                System.out.println("record store file1 is closed");
            }catch (Exception e){
                System.out.println("Error: "+e.getMessage());
            }
        }
        destroyApp(true);
        notifyDestroyed();
    }

    /**
     * Pause the MIDlet
     */
    public void pauseApp() {
    }

    /**
     * Called by the framework before the application is unloaded
     */
    public void destroyApp(boolean unconditional) {
    }
}

Records


Los elementos de un record store se denominan records. Los records se representan por arrays de bytes y se identifican univocamente mediante recordIDs (valores enteros que comienzan en 1). Los records pueden se añadidos, borrados, leidos y modificados a través de los siguientes métodos, proporcionados por el API:


A continuación podeis ver un ejemplo sencillo, que partiendo del primer ejemplo, añade dos records nuevos y borra uno de ellos (RecordStoreTest3.java).

import javax.microedition.midlet.*;
import javax.microedition.rms.*;

public class RecordStoreTest3 extends MIDlet {
    public RecordStoreTest3() {	
    }
    public void startApp() throws MIDletStateChangeException {
        RecordStore rs=null;
        try {
	    rs = RecordStore.openRecordStore("file1",true);
            byte data[]= new byte[4];
            for(int j=0; j<2; j++) {
                int i=rs.getNextRecordID();
                data[0] = (byte)((i >> 24) & 0xff);
                data[1] = (byte)((i >> 16) & 0xff);
                data[2] = (byte)((i >> 8) & 0xff);
                data[3] = (byte)(i & 0xff);
                System.out.println("record "+ rs.addRecord(data,0,4)+" is added.");
            }
		try {
            	rs.deleteRecord(2);
            	System.out.println("record 2 is deleted.");
		}catch(InvalidRecordIDException e) {
			System.out.println("record 2 does not exist");
		}
        }catch(Exception e){}
        finally{
            //close the record store
            try {
	        rs.closeRecordStore();
            }catch (Exception e){}
        }
        destroyApp(true);
        notifyDestroyed();
    }

    /**
     * Pause the MIDlet
     */
    public void pauseApp() {
    }

    /**
     * Called by the framework before the application is unloaded
     */
    public void destroyApp(boolean unconditional) {
    }
}

La cabecera de un Record Store

Los record stores al igual que los ficheros mantienen una cabecera con información propia:



El API nos proporciona además la siguiente información adicional sobre los records store, aunque no está almacenada en la cabecera:



El interfaz RecordListener

A través del interfaz RecordListener se pueden monitorizar cambios en record stores. Se pueden gestionar tres tipos de eventos, a través de los métodos:

La clase RecordStore proporciona los siguientes métodos para añadir o borrar un RecordListener:

NOTA:Un objeto RecordStore puede tener varios RecordListeners registrados.

 RecordEnumeration

Después de que los records se borren, los recordIds de los records que están almacenados en un record store no son consecutivos. Por lo tanto, realizar un recorrido secuencial para obtener todos los records almacenados no es la manera más eficiente de hacerlo.

Para ello se proporciona la clase RecordEnumeration, que aunque en el API de MIDP se presenta como un interfaz, toda implementación de MIDP debe proporcionar una implementación de ella.

Un RecordEnumeration es parecido a un lista doblemente enlazada, en la que cada nodo representa un recordId. Un RecordEnumeration mantiene una secuencia lógica de recordIds de los records almacenados en un record store.

Ejercicio:Analizad el interfaz y realizad un pequeño programa en el que obteneis secuencialmente el contenido de los records en un record store. Cread después un nuevo programa que utilice la implementacion de RecordEnumeration y comprobad la diferencia.


 RecordFilter y RecordComparator


El interfaz RecordFilter define un único método public boolean matches(byte candidate[]) que nos permite definir un criterio para seleccionar un record en un record store que cumpla una determinada condición, de tal forma que si la cumple, se devuelve true y si no false.

El interfaz RecordComparator nos proporciona una forma sencilla de clasificar records. Define una única función int compare(byte[] rec1, byte[] rec2), que puede devolver únicamente los siguientes constantes:



Por ejemplo, una manera de clasificarlos sería por fecha de creación. Así al implentar esta función se devolvería PRECEDES si rec1 se ha creado antes de rec2, FOLLOWS si se ha creado después y EQUIVALENT si se han creado simultaneamente.


 ENLACES


API de MIDP/CLDC




inicio | tablón| contacta