文件序列化,反序列化总结

要点:对于一个文件内多次以添加文本形式写入序列化对象,直接读取时会报错

原因:ObjectOutputStream写入序列化对象时会在写入对象时添加头文件,而每次添加时都会添加一个头文件。

 ObjectInputStream反序列化读取对象时只会识别一次头文件,如果文件内头文件数目大于一则会报错。

解决:自定义一个写序列化的类,继承ObjectOutputStream,重写写入头文件方法;

class MyObjectOutputStream  extends ObjectOutputStream{

  public MyObjectOutputStream(OutputStream out) throws IOException {
      super(out);
  }

  public void writeStreamHeader() throws IOException{
      return;
  }
}

在写入或读出文件时,判断路径是否已存在,提取成一个静态方法:

//判断文件是否存在,如果不存在则自动生成
	public static  File hasFile(String path ) {
		File file = new File(path);
		try {
			// 如果文件不存在,则重新创建该文件
			if (!file.exists()) {
				int i = path.lastIndexOf("/");
				new File(path.substring(0, i)).mkdirs();
				file.createNewFile();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			return file;
		}
	}

序列化写入一个对象示例:

  //添加一个学生对象
	 public static void Addone(Student stu, File file) throws FileNotFoundException, IOException {
		FileOutputStream fos = new FileOutputStream(file, true);
		  if(file.length()<1){//重要的判断
			  ObjectOutputStream oos = new ObjectOutputStream(fos);
			  oos.writeObject(stu);
	            oos.close();
	        }else{
	            MyObjectOutputStream mos = new MyObjectOutputStream(fos);
	            mos.writeObject(stu);
	            mos.close();
	        }
	  	//System.out.println("序列化对象已写入文件" + file.getPath());
	}

file.length()<1,主要在于判断该文件是否已写入过内容,如果写入过则使用自定义的序列化写入类MyObjectOutputStream,如果没有则使用ObjectOutputStream

添加一个集合对象示例:(也是以单个对象形式添加,主要是为了读出时可以顺利读出)

  //重新添加学生对象集合
		public static void Addsom(List<Student >list, File file) throws FileNotFoundException, IOException {
			 //添加集合时一般需要将文件清空重新添加
			if(!(file.length()<1)) {
				file.delete();
			 }
			FileOutputStream fos = new FileOutputStream(file,true);
			 ObjectOutputStream oos  =null;
			 MyObjectOutputStream mos =null;
			for(Student stu:list) {
			 if(file.length()<1){
				  oos = new ObjectOutputStream(fos);
				  oos.writeObject(stu);
		            
		        }else{
		            mos = new MyObjectOutputStream(fos);
		            mos.writeObject(stu);
		          }
			 }
			if(oos!=null) oos.close();
			if(mos!=null) mos.close();
		//  	System.out.println("序列化对象已写入文件" + file.getPath());
		}

 反序列化实体对象

//获得文件中的所有学生对象
	public static List<Student> getAllStu(File file) throws FileNotFoundException, IOException, ClassNotFoundException {
		// 序列化对象读出
		FileInputStream fis = new FileInputStream(file);
		ObjectInputStream ois = new ObjectInputStream(fis);
		List<Student> objArr = new ArrayList<Student>();
		Student p =null;
		 while(fis.available()>0){//判断文件是否已被读完
			   p = (Student) ois.readObject();
			 objArr.add(p);
	        }
		 	ois.close();
		 	 
		 return objArr;
	}

读出对象时如果fis.available()>0
说明可继续读出对象 p = (Student) ois.readObject();

实体类需要实现接口:public class Student implements Serializable

猜你喜欢

转载自blog.csdn.net/qq_38735996/article/details/89010902