RMS从入门到精通之三

在系列之一中,我们着重讲述了Record Management System的基础知识。在介绍如何使用Record Management System之前,我想首先介绍一下Java IO以及在J2ME平台实现序列化的内容,无论对Record Management System还是MIDP中的通用联网框架来说,上述内容都是非常重要的。

    在CLDC中定义的Java IO是非常短小精悍的,但是也提供了足够的类来完成我们的IO操作。由于和J2SE的实现是通用的,因此你可以使用J2ME和J2SE或者J2EE平台进行通信。比如通过联网和servlet进行通信。在Record Management System中我们主要使用的类是ByteArrayInputStream、ByteArrayOutputStream、DataInputStream和DataOutputStream。前面两个是基于字节的,ByteArrayInputStream的作用是把字节数组转换成流而ByteArrayOutputStream的作用是把内存缓冲区内的数据转换成字节。后面两个类是基于java基本数据类型和String操作的。通常他们把前面两个类作为参数传送给构造器,这样他们就可以对基本数据类型以及String进行读写操作了。值得注意的一点是ByteArrayOutputStream的toByteArray()方法是把内存中的数据进行复制返回,这样的话多浪费了一份内存,为了更有效的使用有限的存储空间你可以扩展ByteArrayOutputSteam类然后提供getByteArray()方法,下面是例子:
public class MyByteArrayOutputStream extends ByteArrayOutputStream
{
  public byte[] getByteArray()
  {
    return buf; 
  }
}

    在J2ME中并没有提供对象序列化的机制,但是我们可以自己实现它。请考虑下面这个类:

public class Bank
{
 private String bankName;
 private String phone;
 private int employeeNum;
 
 public Bank(){}
 
 public Bank(String aBankName,String aPhone,int aEmployeeNum)
 {
  this.bankName = aBankName;
  this.phone = aPhone;
  this.employeeNum = aEmployeeNum;
 }
 
 public String getBankName()
 {
  return bankName !=null?bankName:"";
 }
 
 public String getPhone()
 {
  return phone!=null?phone:"";
 }
 
 public int getEmployeeNum()
 {
  return employeeNum;
 }

}
我们添加两个方法到这个类来实现对象序列化。如下所示:
public class Bank
{
 private String bankName;
 private String phone;
 private int employeeNum;
 
 public Bank(){}
 
 public Bank(String aBankName,String aPhone,int aEmployeeNum)
 {
  this.bankName = aBankName;
  this.phone = aPhone;
  this.employeeNum = aEmployeeNum;
 }
 
 public String getBankName()
 {
  return bankName !=null?bankName:"";
 }
 
 public String getPhone()
 {
  return phone!=null?phone:"";
 }
 
 public int getEmployeeNum()
 {
  return employeeNum;
 }
 
 public byte[] serialize() throws IOException
 {
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  DataOutputStream dos = new DataOutputStream(bos);
 
  dos.writeUTF(getBankName());
  dos.writeUTF(getPhone());
  dos.writeInt(getEmployeeNum());
  dos.flush();
 
  return bos.toByteArray();
 }
 
 public Bank deserialize(byte[] data) throws IOException
 {
  ByteArrayInputStream bis = new ByteArrayInputStream(data);
  DataInputStream dis = new DataInputStream(bis);
 
  Bank myBank = new Bank();
  myBank.bankName = dis.readUTF();
  myBank.phone = dis.readUTF();
  myBank.employeeNum = dis.readInt();
 
  return myBank;
 }
}
这样我们就实现了对象的序列化,使用起来也非常简单。序列化和反序列化的操作分别如下面所示:
Bank aBank = .....;
RecordStore rs = .....;
try
{
 byte[] data = aBank.serialize();
 rs.addRecord(data,0,data.length);
}

catch(IOException e)
{
 //do something
}

catch(RecordStoreException e)
{
 //do something
}
————————————————————————————

byte[] data = ..........;
Bank aBank = null;
try
{
 aBank = Bank.deserialize(data);
}
catch(IOException e)
{
 
}
    值得注意的一点是在Bank类中我们的成员都是基本数据类型以及String类型,并不存在指向其他对象的引用,这是最理想也是最简单的情况,事实上我们在J2ME中设计序列化的类的时候也应该尽量这样做,避免不必要得麻烦。

 nbsp;   

 

Record #4 of length 57 bytes

6b 6f 42 1d 5b 65 2f 72 0f 7a  koB.[e/r.z

2a 6e 07 57 51 71 5f 68 4c 5c  *n.WQq_hL/

1a 2a 44 7b 02 7d 19 73 4f 0b  .*D{.}.sO.

75 03 34 58 17 19 5e 6a 5e 80  u.4X..^j^?

2a 39 28 5c 4a 4e 21 57 4d 75  *9(/JN!WMu

80 68 06 26 3b 77 33           ?h.&;w3  

Actual size of records = 153

-----------------------------------------

这种样式方便在wtk中显示,在实际的设备中进行测试的时候,你可能希望把分析输出到串口或者通过网络发到servlet,你可以通过定义自己的类实现实现Logger接口,然后把这个类作为RMSAnalyzer构造器的参数。下面是源代码。

package com.ericgiguere;

import java.io.*;

import javax.microedition.rms.*;

// Analyzes the contents of a record store.

// By default prints the analysis to System.out,

// but you can change this by implementing your

// own Logger.

public class RMSAnalyzer {

    // The logging interface.

    public interface Logger {

        void logEnd( RecordStore rs );

        void logException( String name, Throwable e );

        void logException( RecordStore rs, Throwable e );

        void logRecord( RecordStore rs, int id,

                        byte[] data, int size );

        void logStart( RecordStore rs );

    }

    private Logger logger;

    // Constructs an analyzer that logs to System.out.

    public RMSAnalyzer(){

        this( null );

    }

    // Constructs an analyzer that logs to the given logger.

    public RMSAnalyzer( Logger logger ){

        this.logger = ( logger != null ) ? logger :

                                           new SystemLogger();

    }

   // Open the record stores owned by this MIDlet suite

    // and analyze their contents.

    public void analyzeAll(){

        String[] names = RecordStore.listRecordStores();

        for( int i = 0;

             names != null && i < names.length;

             ++i ){

            analyze( names[i] );

        }

    }

    // Open a record store by name and analyze its contents.

    public void analyze( String rsName ){

        RecordStore rs = null;

        try {

            rs = RecordStore.openRecordStore( rsName, false );

            analyze( rs );

        } catch( RecordStoreException e ){

            logger.logException( rsName, e );

        } finally {

            try {

                rs.closeRecordStore();

            } catch( RecordStoreException e ){

                // Ignore this exception

            }

        }

    }

    // Analyze the contents of an open record store using

    // a simple brute force search through the record store.

    public synchronized void analyze( RecordStore rs ){

        try {

            logger.logStart( rs );

            int    lastID = rs.getNextRecordID();

            int    numRecords = rs.getNumRecords();

            int    count = 0;

            byte[] data = null;

            for( int id = 0;

                 id < lastID && count < numRecords;

                 ++id ){

                try {

                    int size = rs.getRecordSize( id );

                    // Make sure data array is big enough,

                    // plus add some for growth

                   if( data == null || data.length < size ){

                        data = new byte[ size + 20 ];

                    }

                    rs.getRecord( id, data, 0 );

                    logger.logRecord( rs, id, data, size );

                    ++count; // only increase if record exists

                }

                catch( InvalidRecordIDException e ){

                    // just ignore and move to the next one

                }

                catch( RecordStoreException e ){

                    logger.logException( rs, e );

                }

            }

        } catch( RecordStoreException e ){

            logger.logException( rs, e );

        } finally {

            logger.logEnd( rs );

        }

    }

    // A logger that outputs to a PrintStream.

    public static class PrintStreamLogger implements Logger {

        public static final int COLS_MIN = 10;

        public static final int COLS_DEFAULT = 20;

         private int   cols;

        private int  numBytes;

        private StringBuffer hBuf;

        private StringBuffer cBuf;

        private StringBuffer pBuf;

        private PrintStream  out;

         public PrintStreamLogger( PrintStream out ){

            this( out, COLS_DEFAULT );

        }

         public PrintStreamLogger( PrintStream out, int cols ){

 

            this.out = out;

            this.cols = ( cols > COLS_MIN ? cols : COLS_MIN );

        }

         private char convertChar( char ch ){

            if( ch < 0x20 ) return '.';

            return ch;

        }

         public void logEnd( RecordStore rs ){

            out.println( "/nActual size of records = "

                         + numBytes );

            printChar( '-', cols * 4 + 1 );

             hBuf = null;

            cBuf = null;

            pBuf = null;

        }

         public void logException( String name, Throwable e ){

            out.println( "Exception while analyzing " +

                         name + ": " + e );

        }

         public void logException( RecordStore rs, Throwable e ){

            String name;

             try {

                name = rs.getName();

            } catch( RecordStoreException rse ){

                name = "";

            }

             logException( name, e );

        }

         public void logRecord( RecordStore rs, int id,

                               byte[] data, int len ){

            if( len < 0 && data != null ){

                len = data.length;

            }

            hBuf.setLength( 0 );

            cBuf.setLength( 0 );

             numBytes += len;

             out.println( "Record #" + id + " of length "

                         + len + " bytes" );

             for( int i = 0; i < len; ++i ){

                int    b = Math.abs( data[i] );

                String hStr = Integer.toHexString( b );

                 if( b < 0x10 ){

                    hBuf.append( '0');

                }

                 hBuf.append( hStr );

                hBuf.append( ' ' );

                 cBuf.append( convertChar( (char) b ) );

                 if( cBuf.length() == cols ){

                    out.println( hBuf + " " + cBuf );

                     hBuf.setLength( 0 );

                    cBuf.setLength( 0 );

                }

            }

             len = cBuf.length();

             if( len > 0 ){

                while( len++ < cols ){

                    hBuf.append( "   " );

                    cBuf.append( ' ' );

                }

                 out.println( hBuf + " " + cBuf );

            }

        }

         public void logStart( RecordStore rs ){

            hBuf = new StringBuffer( cols * 3 );

            cBuf = new StringBuffer( cols );

            pBuf = new StringBuffer();

             printChar( '=', cols * 4 + 1 );

             numBytes = 0;

            try {

                out.println( "Record store: "

                             + rs.getName() );

                out.println( "    Number of records = "

                             + rs.getNumRecords() );

                out.println( "    Total size = "

                             + rs.getSize() );

                out.println( "    Version = "

                             + rs.getVersion() );

                out.println( "    Last modified = "

                             + rs.getLastModified() );

                out.println( "    Size available = "

                             + rs.getSizeAvailable() );

                out.println( "" );

            } catch( RecordStoreException e ){

                logException( rs, e );

 

            }

        }

         private void printChar( char ch, int num ){

            pBuf.setLength( 0 );

            while( num-- > 0 ){

                pBuf.append( ch );

            }

            out.println( pBuf.toString() );

        }

    }

    // A logger that outputs to System.out.

    public static class SystemLogger extends PrintStreamLogger
   {

        public SystemLogger(){

            super( System.out );

        }

        public SystemLogger( int cols ){

            super( System.out, cols );

        }

    }

你可能感兴趣的:(RMS从入门到精通之三)