這幾天做一個小的聊天項目用到對象序列化的知識,發現對象序列化不能像普通文件一樣直接追加對象。每次寫入對象都會被覆蓋。弄了2個多小時終於解決了。Java默認的對象序列化是每次寫入對象都會寫入一點頭aced 0005(占4個字節),然后每次讀取都讀完頭然后在讀內容。解決方法就是先判斷文件是否存在。如果不存在,就先創建文件。然后寫了第一個對象,也寫入了頭aced 0005。追加的情況就是當判斷文件存在時,把那個4個字節的頭aced 0005截取掉,然后在把對象寫入到文件。這樣就實現了對象序列化的追加。代碼如下:
首先我們要寫一個對類,用於對象的序列化,這個類實現了Serializable接口。類的定義如下:
package qq.client.tools; import java.io.*; /** * 這是對象序列化的程序 * 實現了對象序列化的追加 * @author Administrator * */ public class ObjectOutputTest { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Message m = new Message(); m.setName("aaaaaaaaaaaaaaaaaaaaa"); File file=new File("D:\\jjm.txt"); boolean isexist=false;//定義一個用來判斷文件是否需要截掉頭aced 0005的 if(file.exists()){ //文件是否存在 isexist=true; FileOutputStream fo=new FileOutputStream(file,true); ObjectOutputStream oos = new ObjectOutputStream(fo); long pos=0; if(isexist){ pos=fo.getChannel().position()-4;//追加的時候去掉頭部aced 0005 fo.getChannel().truncate(pos); } oos.writeObject(m);//進行序列化 System.out.println("追加成功"); }else{//文件不存在 file.createNewFile(); FileOutputStream fo=new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fo); oos.writeObject(m);//進行序列化 oos.close(); System.out.println("首次對象序列化成功!"); } } }
下面是反系列化的實現。注意要在循環外面關閉流,在里面關閉會出現句柄無效的錯誤。
package qq.client.tools; import java.io.*; public class ObjectInputTest { /**這是反序列化的程序 * 實現從文件讀取多個對象 * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub File file = new File("D:"+File.separator+"jjm.txt"); if(file.exists()){ ObjectInputStream ois; try { FileInputStream fn=new FileInputStream(file); ois = new ObjectInputStream(fn); while(fn.available()>0){//代表文件還有內容 Message p = (Message)ois.readObject();//從流中讀取對象 System.out.println(p.getName()); } ois.close();//注意在循環外面關閉 } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }
整個序列化對象的追加與從文件讀取多個對象實就實現了。