| Record Management System是MIDP的子系统,提供了数据的持久性存储功能,本文并非讲述Record Management System的基础知识,而是从编程的角度提出高效使用Record Management System的建议。如果您对RMS还不够了解请参考本专题其他的文章。
在RecordStore中存储的数据是以字节的形势存在的,MIDP规范中并没有规定什么数据可以存储在RMS中,只要他可以转换成字节数组。那么读取和写入这些字节数据的时候我们应该注意些什么问题呢?由于非挥发性内存的存取速度都比较慢,因此我们应该尽量的少对RMS进行写操作,当然这也和设备有关系,有些设备的写操作是非常好费资源的。在读取数据的时候我们应该尽量复用对象,避免大量的创建对象然后丢弃对象,这样会给Heap和GC造成不小的负担。
看下面读取数据的两个不同的代码片断 //片断1 RecordStore rs = ....; // an open record store
try { int lastID = rs.getNextRecordID(); byte[] data; for( int i = 0; i < lastid; ++i ){ try { data = rs.getrecord( i ); .... // do something with the data } catch( invalidrecordidexception e ){ continue; } } } catch( exception e ){ // error }
//片断2 RecordStore rs = ....; // an open record store
try { RecordEnumeration enum = rs.enumerateRecords( null, null, false ); while( enum.hasNextElement() ){ byte[] data = enum.nextRecord(); .... // do something with the data } } catch( Exception e ){ // error }
上面的代码存在的问题是系统每次读取记录都要创建新的字节数组对象,这显然不够高效。其实我们可以对字节数组进行复用,并可以适当的调整它的大小。 RecordStore rs = ....; // an open record store
try { RecordEnumeration enum = rs.enumerateRecords( null, null, false ); byte[] data = new byte[100]; int len = 0; while( enum.hasNextElement() ){ int id = enum.nextRecordId();
len = rs.getRecordSize( id ); if( len > data.length ){ // add a growth factor data = new byte[ len + 40 ]; } rs.getRecord( id, data, 0 );
// do something with the data } } catch( Exception e ){ // error }
在我们读取数据的时候,通常还会用到javaIO,比如ByteArrayInputStream和DataInputStream类,那么在使用他们的时候,我们也应该尽量复用对象。比如当我们从RMS中读取纪录的时候,假设纪录包括一个布尔型和两个整型数据。 RecordStoreEnumeration enum = ...; // get a record enumeration byte[] data = new byte[9]; // record size ByteArrayInputStream bin = new ByteArrayInputStream( data ); DataInputStream din = new DataInputStream( bin );
while( enum.hasNextElement() ){ int id = enum.nextRecordId(); getRecord( id, data, 0 ); din.reset(); // move stream back to start boolean first = din.readBoolean(); int second = din.readInt(); int third = din.readInt(); // do something here }
下面提供一个封装好的Record类,你可以在使用RMS的时候使用它 import java.io.*; import javax.microedition.rms.*;
public class Record implements DataInput {
private RecordStore _rs; private byte[] _data; private int _length; private int _id; private DataInputStream _din;
public Record( RecordStore rs ){ this( rs, 100 ); }
public Record( RecordStore rs, int initialRecordSize ){ _rs = rs; _data = new byte[ initialRecordSize ]; _din = new DataInputStream( new ByteArrayInputStream( _data ) ); _length = -1; }
public byte[] getByteArray() { return _data; }
public int getLength() { return _length; }
public byte[] moveTo( int id ) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException, IOException { _length = _rs.getRecordSize( id );
if( _length > _data.length ){ _data = new byte[ _length + 40 ]; _din = new DataInputStream( new ByteArrayInputStream( _data ) ); }
_rs.getRecord( id, _data, 0 ); _id = id; _din.reset();
return _data; }
public void readFully(byte b[]) throws IOException { _din.readFully( b ); }
public void readFully(byte b[], int off, int len) throws IOException { _din.readFully( b, off, len ); } return _din.skipBytes( n ); }
public boolean readBoolean() throws IOException { return _din.readBoolean(); } public byte readByte() throws IOException { return _din.readByte(); }
public int readUnsignedByte() throws IOException { return _din.readUnsignedByte(); }
public short readShort() throws IOException { return _din.readShort(); }
public int readUnsignedShort() throws IOException { return _din.readUnsignedShort(); }
public char readChar() throws IOException { return _din.readChar(); } public int readInt() throws IOException { return _din.readInt(); }
public long readLong() throws IOException { return _din.readLong(); }
public String readUTF() throws IOException { return _din.readUTF(); } }
使用起来非常简单 try { rs = RecordStore.openRecordStore( "mydata", true ); // Write two records to the record store
ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream( bout ); byte[] data;
dout.writeUTF( "this is a test" ); dout.writeInt( 1 ); dout.flush(); data = bout.toByteArray();
rs.addRecord( data, 0, data.length );
bout.reset(); dout.writeUTF( "this is another test" ); dout.writeInt( 99 ); dout.flush(); data = bout.toByteArray();
rs.addRecord( data, 0, data.length ); // Now read through the record store
Record record = new Record( rs ); int lastID = rs.getNextRecordID(); RecordEnumeration enum = rs.enumerateRecords( null, null, while( enum.hasNextElement() ){ int id = enum.nextRecordId(); record.moveTo( id ); System.out.println( record.readUTF() + " " + record.readInt() ); }
rs.closeRecordStore(); } catch( Exception e ){ // handle error } |