作者:mingjava 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=7 本文将主要讲述RecordFilter和RecordEnumeration的用法,这在整个Record Management System中都是至关重要的。由于本人觉得RecordComparator和RecordFilter类似并且用出相对小些,因此不再这里做介绍了。我们依然是通过一个示范的应用程序说明如何使用这两个接口。 RecordFilter的定义非常的简单,他只定义了一个方法那就是boolean matches(byte[] data)。 public interface RecordFilter { boolean matches( byte[] recordData ); } 使用起来也非常简单,我们只需要实现这个方法并根据需要返回boolean类型的值就可以了,通常我们在查找纪录的时候使用这个接口,把它作为一个参数传递给enumerateRecords()方法,例如 RecordEnumeration records = rs.enumerateRecords(new RecordEntryFilter(key),null,false),首先我们看看这个方法的参数,第一个参数是RecordFilter,它就是用来筛选数据库中的纪录的,筛选的条件就是我们上面定义的方法,boolean matches(byte[] data),第二个参数是RecordComparator,它是对选择出来的数据进行排序的,如果你不指定的话就按照默认的顺序排序。第三个参数是boolean类型的,如果是true的话,那么record会跟踪rms中的数据变化,这是比较昂贵的开销,我一般都是用false的。得到records后我们可以进行很多有用的操作,具体的方法有: public interface RecordEnumeration { void destroy(); boolean hasNextElement(); boolean hasPreviousElement(); boolean isKeptUpdated(); void keepUpdated( boolean keepUpdated ); byte[] nextRecord() throws InvalidRecordIDException, RecordStoreNotOpenException, RecordStoreException; int nextRecordId() throws InvalidRecordIDException; int numRecords(); byte[] previousRecord() throws InvalidRecordIDException, RecordStoreNotOpenException, RecordStoreException; int previousRecordId() throws InvalidRecordIDException; void rebuild(); void reset(); } 其中标记的方法很常用应该记住。我们实现RecordFilter的时候通常是会写成一个类的内部类,这非常普遍也很合理。我下面的程序依然使用这样的方法, private static class RecordEntryFilter implements RecordFilter { private String key; public RecordEntryFilter(String key) { this.key = key; } public boolean matches(byte[] data) { try { return RecordEntry.matches(data, key); } catch (IOException e) { e.printStackTrace(); return false; } } } 在例子用我们向RMS中存入几个数据实体,它包括一个username和一个phonenumber字段。我们写入和读出字段的时候可以使用系列之二中的序列化机制。 import java.io.*; public class RecordEntry { private String userName; private String phoneNum; public RecordEntry() { } public RecordEntry(String userName, String phoneNum) { this.userName = userName; this.phoneNum = phoneNum; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public byte[] serialize() throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeUTF(userName); dos.writeUTF(phoneNum); return baos.toByteArray(); } public static RecordEntry deserialize(byte[] data) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bais); RecordEntry record = new RecordEntry(); record.userName = dis.readUTF(); record.phoneNum = dis.readUTF(); return record; } public static boolean matches(byte[] data,String key) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bais); return dis.readUTF().equals(key); } public String toString() { return userName+":"+phoneNum; } } 我们本文要讲述的另一个重点是如何使用RecordEnumeration,相关的代码写在了一个RecordModel类里面如下: import java.io.IOException; import javax.microedition.rms.*; public class RecordModel { private RecordStore rs; private boolean firstTime = true; public static final String NAME = "record"; private RecordEntry[] record = { new RecordEntry("ming", "12345"), new RecordEntry("pain", "123456"), new RecordEntry("linux", "234566"), new RecordEntry("mingtian", "3456677") }; private static class RecordEntryFilter implements RecordFilter { private String key; public RecordEntryFilter(String key) { this.key = key; } public boolean matches(byte[] data) { try { return RecordEntry.matches(data, key); } catch (IOException e) { e.printStackTrace(); return false; } } } public RecordModel() { try { rs = RecordStore.openRecordStore(NAME, true); } catch (RecordStoreException e) { e.printStackTrace(); } if(firstTime) { init(); firstTime = false; } } public void init() { try { for (int i = 0; i < record.length; i++) { byte[] data = record[i].serialize(); rs.addRecord(data, 0, data.length); } } catch (IOException e) { e.printStackTrace(); } catch (RecordStoreException e) { e.printStackTrace(); } } public RecordEntry[] getRecord(String key) { try { if (rs.getNumRecords() > 0) { RecordEnumeration records = rs.enumerateRecords( new RecordEntryFilter(key), null, false); int length = records.numRecords(); if (length == 0) { return new RecordEntry[0]; } else { System.out.println(length); RecordEntry[] record = new RecordEntry[length]; for (int i = 0; i < length; i++) { record[i] = RecordEntry.deserialize(rs .getRecord(records.nextRecordId())); } return record; } } else { return new RecordEntry[0]; } } catch (RecordStoreException e) { e.printStackTrace(); return new RecordEntry[0]; } catch (IOException e) { e.printStackTrace(); return new RecordEntry[0]; } } } 其中标记为灰色的代码是我们应该重点掌握的,下面是RecordFilterMIDlet类的代码: import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class RecordFilterMIDlet extends MIDlet implements ItemStateListener { private Display display; private Form mainForm; private TextField textField; private RecordModel model; protected void startApp() throws MIDletStateChangeException { display = Display.getDisplay(this); mainForm = new Form("Test"); model = new RecordModel(); textField = new TextField("input:", null, 20, TextField.ANY); mainForm.append(textField); mainForm.setItemStateListener(this); display.setCurrent(mainForm); } protected void pauseApp() { } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { } public void itemStateChanged(Item item) { if (item == textField) { String input = textField.getString(); RecordEntry[] record = model.getRecord(input); if (record.length == 0) { System.out.println("no record"); } else { for (int i = 0; i < record.length; i++) { System.out.println(record[i]); } } } } } 为了方便我没有在手机界面上显示,而是输出到控制台。下面是在input内输入ming的时候在控制台打印出来的结果: no record no record no record 1 ming:12345 你可能想把以输入字段为开头的记录筛选出来,就像在通讯录中查询一样。那么你可以在Filter中添加一个int类型的type来告诉实体中的matches()方法应该如何做。这样就可以筛选出你所需要的记录了:) 还是那句话,希望对大家有用!本来还想在系列5中介绍我自己实现的一个个人通信录,程序已经写完,大概有3k的代码吧,基本覆盖了前面所讲述的专题。由于我准备投稿,因此决定不继续写Record Management System的内容了。 |