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
}