Hasta ahora hemos usado la memoria principal del m�vil (la RAM) para almacenar datos temporales, pero al salir del midlet, estos datos son eliminados. Esto plantea algunos problemas. Por ejemplo, �c�mo podemos almacenar las puntuaciones m�ximas de nuestro juego?
Un dispositivo m�vil (al menos por ahora) no dispone de disco duro donde almacenar informaci�n permanentemente. J2ME resuelve el problema mediante el RMS (Record Management System). RMS es un peque�o sistema de bases de datos muy sencillo, pero que nos permite a�adir informaci�n en una memoria no vol�til del m�vil. RMS no tiene nada que ver con JDBC debido a las limitaciones de los dispositivos J2ME, por lo tanto, el acceso y almacenamiento de la informaci�n se hace a mucho m�s bajo nivel. RMS no puede ser consultado con sentencias SQL ni nada parecido. En una base de datos RMS, el elemento b�sico es el registro (record). Un registro es la unidad de informaci�n m�s peque�a que puede ser almacenada. Los registros son almacenados en un recordStore que puede visualizarse como una colecci�n de registros. Cuando almacenamos un registro en el recordStore, a �ste se le asigna un identificador �nico que identifica un�vocamente al registro.
Para poder utilizar RMS hemos de importar el paquete javax.microedition.rms. Este paquete nos provee de la clase RecordStore y de cuatro interfaces, de las cuales solamente profundizaremos en la interfaz RecordEnumeration.
�Trabajando con RMS
Cubrir todas las capacidades de RMS se escapa del �mbito de este libro. Sin entrar en profundidades, vamos a ver c�mo realizar las operaciones b�sicas de almacenamiento, lectura y borrado de registros.
�Abrir y errar un recordStore
Antes de poder almacenar un registro hemos de abrir un recordStore con el m�todo openRecordStore().
static RecordStore openRecordStore(String nombre, bolean crear)
El par�metro nombre es el nombre de la base de datos. El nombre puede tener un tama�o de 32 caracteres. El par�metro crear, si tiene su valor a true, crear� la base de datos si no existe. Cuando creamos un recordStore, s�lo puede ser accedido desde la suite de MIDlets que la cre�.
Cuando terminamos de utilizar el recordStore, hemos de cerrarlo:
RecordStore.closeRecordStore();
�A�adir registros
Una vez abierto nuestro recordStore podemos comenzar a a�adir registros con el m�todo addRecord().
public int addRecord(byte[]�dato,int�offset, int�numBytes)
El primer par�metro es el dato que queremos almacenar. Es un array de bytes. El offset es la posici�n a partir de la cual (dentro del array) se va a almacenar el dato. Finalmente, numBytes es el n�mero de bytes que se van a almacenar. El m�todo retorna el identificador que el RMS ha asignado al registro.
El m�todo addRecord puede lanzar la excepci�n RecordStoreException, por lo tanto hemos de capturarla.
try {
int id = recordStore.addRecord (datos, 0, datos.length);
} catch (RecordStoreException e) {}
�Leer registros
El m�todo getRecord() permite acceder al registro que deseemos, siempre que conozcamos su identificador.
public byte[] getRecord(int�Id)
No es necesario que almacenemos y mantengamos una lista con todos los identificadores de los registros. Un poco m�s adelante veremos el m�todo recordEnumeration que nos permitir� conocer el identificador de cada registro. Al igual que con el m�todo addRecord(), hemos de capturar la excepci�n RecordStoreException.
byte[] dato = null;
try {
dato = recordStore.getRecord(id);
} catch (RecordStoreException e) {}
�Borrar registros
El borrado de registros se realiza con el m�todo deleteRecord().
public void deleteRecord(int�recordId)
Al igual que con la escritura y lectura de registros hemos de tener en cuenta que puede provocar la excepci�n RecorStoreException.
try {
recordStore.deleteRecord(id);
} catch (RecordStoreException e) {}
�Recorriendo registros
Vamos a valernos del objeto RecordEnumeration para recorrer todos los registros almacenados en la base de datos. Para crear una enumeraci�n utilizamos el m�todo enumerateRecords().
public RecordEnumeration enumerateRecords(RecordFilter�filtro,
RecordComparator, comparador,boolean�Actualizar)
Los dos primeros par�metros sirven para personalizar el recorrido de los registros. No entraremos en detalle, pero, gracias al primero podremos filtrar la b�squeda, y con el segundo podemos recorrer los registros de forma ordenada. El par�metro Actualizar indica si la enumeraci�n debe actualizarse cuando realicemos alguna operaci�n de inserci�n o borrado de registros. Si vas a hacer un recorrido r�pido por los registros es mejor ponerlo a false para evitar la sobrecarga.
RecordEnumeration registro = null;
try {
registro = recordStore.enumerateRecords(null, null, false);
while (registro.hasNextElement())
System.out.println (registro.nextRecordId());
} catch (Exception e) {}
Hay dos m�todos interesantes del RecordEnumeration: hasNextElement() que devolver� el valor true si hay un siguiente elemento disponible para ser le�do. Cada vez que leemos un elemento se adelanta el puntero al siguiente. El m�todo nextRecordId() devuelve el identificador del siguiente registro.
El siguiente c�digo muestra un ejemplo completo de uso de RMS.
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
public class RMS extends MIDlet {
// nombre de la BD
static final String BD = "datos";
String dato;
int id, i;
char b;
public RMS() {
RecordStore rs = null;
// Borramos la BD si ten�a algo
try {
RecordStore.deleteRecordStore(BD);
} catch( Exception e ){}
try {
// Abrimos el recordStore
rs = RecordStore.openRecordStore(BD, true);
guardaRegistro(rs,"Datos del registro 1");
guardaRegistro(rs,"Datos del registro 2");
guardaRegistro(rs,"Datos del registro 3");
// Leemos los registros
RecordEnumeration registros = rs.enumerateRecords(null, null, false);
// Recorremos todos los elementos
while (registros.hasNextElement()) {
// Obtenemos el ID del siguiente registro
verRegistro(rs, registros.nextRecordId());
}
rs.closeRecordStore();
} catch( RecordStoreException e ){
System.out.println( e );
}
notifyDestroyed();
}
public void verRegistro(RecordStore rs, int id) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(rs.getRecord(id));
DataInputStream is = new DataInputStream(bais);
// leemos el registro
try {
dato = is.readUTF();
System.out.println("-> "+dato);
} catch (EOFException eofe) {
} catch (IOException ioe) {}
} catch (RecordStoreException e) {}
}
public void guardaRegistro(RecordStore rs, String dato) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(baos);
try {
// guadar el dato
os.writeUTF(dato);
} catch (IOException ioe) {}
// extraer el array de butes
byte[] b = baos.toByteArray();
// lo a�adimos al recordStore
try {
rs.addRecord(b, 0, b.length);
} catch (RecordStoreException rse) {}
}
public void destroyApp( boolean unconditional ) {}
public void startApp() {}
public void pauseApp() {}
}