posts - 0,  comments - 3,  trackbacks - 0

java的序列化和反序列化;

定义:序列化是指把一个对象写到一个输出流中;对象的反序列化是指从一个输入流中读取一个对象.只要实现了java.io.Serializable(标识接口)接口的对象才能被序列化和反序列化;

序列化的步骤:

1).创建一个对象输出流,它可以包装一个其他类型的输出流,比如文件输出流.

ObjectOutputStream out=new ObjectOutputStream(new fileOutputStream("c:/a.obj"));

2).通过对象输出流的writeObject()方法写对象

out.writeObject("hello");

out.close;

以上代码将一个String 对象保存到文件中.

对象的反序列化步骤:

1).创建一个对象输入流,他可以包装一个其他类型的输入流,例如文件输入流.

 ObjectInputStream in=new ObjectInputStream(new FileInputStream("c:/a.obj"));

2).通过对象输入流的readObject()方法读取对象.

 String obj=(String)in.readObject();

 in.close();

当写入多个对象时,为了能正确读出数据,必须保证向输出流写对象的顺序与从输入流读对象的顺序相同.

一个简单的序列化 反序列化的例子:

=======================================================================================

Customer类(实现了Serializable标识接口)

import java.io.Serializable;
import java.util.Date;

public class Customer implements Serializable {
 private String name;
 private Date birthday;
 private transient String password; 注释①
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public Customer(String name,String password)
 {
  this.name=name;
  this.birthday=new Date();
  this.password=password;
 }
 public Date getBirthday() {
  return birthday;
 }
 public void setBirthday(Date birthday) {
  this.birthday = birthday;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 
 }

}
ObjectSaver类:执行序列化,将类写到文件中

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

public class ObjectSaver 
{
 public ObjectSaver()
 {
  try {
   ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("c:/a.obj"));
   String obj1="序列化对象";
   Date obj2=new Date();
   Customer obj3=new Customer("jalion","123456");
   //序列化对象
   out.writeObject(obj1);
   out.writeObject(obj2);
   out.writeObject(obj3);
   out.close();
   System.out.println("需要序列化的对象:"+obj1);
   System.out.println("需要序列化的对象:"+obj2);
   System.out.println("需要序列化的对象:"+obj3.getName()+"生日"+obj3.getBirthday()+"密码:"+obj3.getPassword());

   
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 public static void main(String args[])
 {
  new ObjectSaver();
 }
}
ObjectRead:反序列化类 从文件中读取对象


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Date;

public class ObjectRead {
 public static void main(String args[])
 {
//  反序列化对象
  ObjectInputStream in;
  try {
   in = new ObjectInputStream(new FileInputStream("c:/a.obj"));
   String obj11=(String)in.readObject();
   Date obj22=(Date)in.readObject();
   Customer obj33=(Customer)in.readObject();
   System.out.println("反序列化的对象:"+obj11);
   System.out.println("反序列化的对象:"+obj22);
   System.out.println("反序列化的对象:"+obj33.getName()+"生日"+obj33.getBirthday()+"密码:"+obj33.getPassword());
   in.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 
 }

}

说明:由于String和Date类都实现了Serializable接口,所以可以序列化,要进行序列化的类包括其属性中引用的类必须全部实现Serializable接口才能序列化,否则将会抛出java.io.NotSerializableException异常.

========================================================================================

注释①在类Customer中,有个属性password,由于将类序列化保存在文件中,可以通过网络传输,当password比较重要时,很容易通过读取文件或者拦截网络数据来得到password,所以应当禁止对这种属性序列化.解决办法就是将这个属性用transient修饰,例如例子中的注释处.当属性有transient修饰时,不进行序列化.

ObjectRead运行结果如下:

当有transient修饰时:

反序列化的对象:序列化对象
反序列化的对象:Tue May 08 10:56:40 CST 2007
反序列化的对象:jalion生日Tue May 08 10:56:40 CST 2007密码:null

当没有transient修饰时:

反序列化的对象:序列化对象
反序列化的对象:Tue May 08 10:56:40 CST 2007
反序列化的对象:jalion生日Tue May 08 10:56:40 CST 2007密码:123456

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

除了用以上方案,来保证传输过程中的安全,还可以用通过进一步控制序列化和反序列化的方式,来达到将password加密或其他方式来实现序列化.

可以在Costumer类中提供一个readObject()和writeObject()方法,当ObjectOutputStream对一个对象序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法,否则就按默认的方式序列化,在writeObject()方法中,可以调用defaultWriteObject()方法,使得对象输出流执行默认的序列化操作.反序列化同理.在修改后的Costumer类中,提供了readObject()和writeObject()方法,使得transient类型的password属性能够进行特殊的序列化

private void writeObject(ObjectOutputStream stream){}

private void readObject (ObjectInputStream stream) {}

以上两个方法并不是在Serializable接口中实现的.如果要进一步控制序列化的方式,就可以实现这两个方法,方法名必须与方法完全一致.

=========================================================================

修改后的Customer类

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;

public class Customer implements Serializable {
 private String name;
 private Date birthday;
 private transient String password;

 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public Customer(String name,String password)
 {
  this.name=name;
  this.birthday=new Date();
  this.password=password;
  
 }
 public Date getBirthday() {
  return birthday;
 }
 public void setBirthday(Date birthday) {
  this.birthday = birthday;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 
 }
 private void writeObject(ObjectOutputStream stream)
 {
  try {
   stream.defaultWriteObject();//先按默认的方式序列化
   stream.writeObject(jiami(password));
  } catch (Exception e) {
   // TODO 自动生成 catch 块
   e.printStackTrace();
  }
  
 }
 private void readObject(ObjectInputStream stream)
 {
  try {
   
   stream.defaultReadObject();//先按默认的方式反序列化
   password=jiemi((String)stream.readObject());
  } catch (Exception e) {
   // TODO 自动生成 catch 块
   e.printStackTrace();
  }
  
 }
 private String jiami(String password) //加密解密示意
 {
  return "gthgthg"+password;
 }
 private String jiemi(String password) //解密示意
 {
  String s=password.substring(7,password.length());
  return s;
 }

}

posted on 2007-07-01 10:08 李桢 阅读(594) 评论(0)  编辑  收藏 所属分类: java
<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

留言簿(1)

文章分类

文章档案

搜索

  •  

最新评论