自己实现RMI(三)对象序列化与反序列化

        对象的序列化就是把对象的状态用字符串或者byte数组表示,以方便在网络上传输或者将数据写入文件。而反序列化即根据字符串或者byte数组欢迎对象的状态。一般常用的序列化方法是xml序列化,将对象的各个属性写入xml,然后用网络发送到远方,远方收到xml后创建一个空对象,最后根据xml的信息欢迎对象的状态。

        当然用json来序列化要比xml要高效很多。但是,经过实验研究发现json还有优化空间,于是本人设计了一套CommaString用于优化序列化过程。CommaString,顾名思义,即逗号字符串,比如一个对象A,其中有两个属性:整数10,字符串“hello”。对象A序列化后为:10,“hello"。这样比json要少一些字符,当然,逗号字符串中各个数据的顺序必须严格一致,即序列化时写入的顺序和反序列化时读取的顺序必须一样。在很多情况下,序列化和反序列化的实现是同一个人,即RMI的双方知道序列化的顺序,所以逗号字符串还是有可用的地方的。

序列化

        下面以添加字符串举例说明序列化过程。

public void putString(String src)
{		
	if(src==null)
	{
		putString("null");
		return;
	}
	if(stringBuffer.length()>0)
		stringBuffer.append(",");
	stringBuffer.append(src);			
}
        其中stringBuffer是一个StringBuffer,用这个也是出于效率的考虑。序列化接口很简单,如果是string类型,只需要把string放入buffer中即可,如果是int或者double等基础类型,则转为string类型再放入buffer中。

        至于数组类型、list、set等二维数据类型,则先将其大小放入buffer,然后再将各个元素一一放入buffer。如下:

public void putIntArray(int[] data)
{
	int i;
	int[] objIntArray=data;
	putInt(objIntArray.length);
	for(i=0;i<objIntArray.length;i++)
	{
		putInt(objIntArray[i]);
	}
}
        至于hashMap,则首先先将map的大小放入buffer,然后对于每个元素,先放key,后放value。

public void putHashMap(HashMap<String,CommaSerialize> hashMap)
{
	putInt(hashMap.size());
	for(String key:hashMap.keySet())
	{
		putString(key);
		putComma(hashMap.get(key));
	}
}
        最后是object的支持:借用instanceof来判断对象的类型,然后进一步序列化。

public void putObject(Object obj)
{
	if(obj==null)
	{
		putString("null");
		return;
	}
	if(obj instanceof Integer)
	{
		putInt(Integer.parseInt(obj.toString()));
	}
	else if((obj instanceof Float) ||(obj instanceof Double))
	{
		putDouble(Double.parseDouble(obj.toString()));
	}
	else if( obj instanceof String)
	{
		putString(obj.toString());
	}
	else if(obj instanceof Boolean)
	{
		putBoolean(Boolean.parseBoolean(obj.toString()));
	}
	else if(obj instanceof CommaSerialize)
	{			
		((CommaSerialize)obj).toSerialize(this);
	}
	else if(obj instanceof int[])
	{
		putIntArray((int[])obj);
	}
	else if(obj instanceof float[])
	{
		int i;
		float[] objIntArray=(float[])obj;
		putInt(objIntArray.length);
		for(i=0;i<objIntArray.length;i++)
		{
			putDouble(objIntArray[i]);
		}
	}
	else if(obj instanceof double[])
	{
		putDoubleArray((double[])obj);
	}
	else if(obj instanceof String[])
	{
		putStringArray((String[])obj);
	}
	else if(obj instanceof Object[])
	{
		int i;			
		Object[] arrayObjects=(Object[])obj;
		putInt(arrayObjects.length);
		for(i=0;i<arrayObjects.length;i++)
		{
			putObject(arrayObjects[i]);
		}			
	}
	else if(obj instanceof List)
	{
		List<?> objCollection=(List<?>) obj;
		putList(objCollection);
	}
	else if(obj instanceof HashMap)
	{
		putHashMap((HashMap<String, CommaSerialize>)obj);
	}
	else 
	{
		Log.log("CommaString type error with '"+obj.getClass().toString()+"'");
	}		
}
 反序列化
       
序列化后的结果其实还是普通的字符串,只是中间有不少逗号以间隔。反序列化最关键的是以逗号为间隔获取字符串:

public String getNext()
{
	String outString;
	if(sourceString==null || haveNext==false)
		return null;	
	 end=sourceString.indexOf(',',begin);//根据begin end截取子串。
         if(end==-1) 
         {       	
        	 haveNext=false;//没有后续的字符串了
        	 outString=sourceString.substring(begin); //最后一个子串 特殊处理
         }
         else
         {
       	  	outString=sourceString.substring(begin, end);
         }
         begin=end+1; //更新begin 和end,以备下次获取子串
         end++;
         
         if(outString.equals("null"))//约定字符串null为空对象
        	 return null;
         
         return outString;
}
有了上面的方法支持,很方便的反序列化所有对象。例如要反序列化整数数组:

public int[] getIntArray()
{
	int len=getNextInt();
	int i;
	int[] ret=new int[len];
	for(i=0;i<len;i++)
	{
		ret[i]=getNextInt();//以整数为类型获取下一个对象
	}
	return ret;
}
反序列化的过程和序列化的过程恰好相反。其中getNextInt是在getNext的基础上,将获取到的字符串转化为int类型。

对象序列化与反序列化举例:

假如类A有两个成员:int a和string b;那么类A的序列化函数和反序列化函数可以如下实现:

@Override
public void toSerialize(CommaString writer) {
	// TODO Auto-generated method stub
		
	writer.putObject(a);
	writer.putObject(b);
}

@Override
public void deSerialize(CommaString args) {
        // TODO Auto-generated method stub			
	
        a = args.getNextInt();
        b = args.getNext();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值