序列化及反序列化

序列化:将对象按照流的方式存储到文本文件中或者再网络中传输    对象---->流数据 序列化流 (ObjectOutputStream)


反序列化:将文本文件中的流对象或者网络传输中的流对象还原成对象   流数据--->对象  反序列化流(ObjectInputStream)

 java.io.NotSerializableException :当前类未实现序列化功能的异常
   
   Serializable:接口 没有构造方法,没有字段,也没有方法
 接口---->标记接口
   
  自定义类要实现序列化功能,必须实现接口Serializable接口
 
 类实现了serializable也意味着他是标记类
 
  假设之前操作针对Peroson操作序列的时候,产生一个标记  Preson.class--->固定ID 100
 
  name -100
age -100
 
   已经序列化完毕了,然后有修改了Person类里面的一些东西,加入了toString()
  Person.class---固定id -- 200

  
 org.westos_01.Person; local class incompatible: 
  stream classdesc serialVersionUID = -428218385429329797, 
local class serialVersionUID = -5865763454468005049


  因为手动修改了这些类的属性/成员变量,将序列化版本Id改变了
 InvalidClassException:一般情况:该类的序列版本号与从流中读取的类描述符的版本号不匹配 
 实际开发中,不想多次对当前这些序列化,如果这样做,非常麻烦?
   如何解决呢?
  让当前实现类序列化功能的这个类产生一个固定ID,注意看程序有黄色警告线,直接就点它固定Id
 

       比如:当前的这个类中有很多属性(性别,地址,学号...),某些属性不想被序列化,如何解决这样一个问题

public class Person implements Serializable{
	
	//产生随机的固定Id
	private static final long serialVersionUID = 3929786557947102117L;

	private String name ;
//	private int age ;
//	public int age ;
	
	transient int age  ;//这样这个类的属性就不会被序列化
	
	public Person() {
		super();
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

public class ObjectDemo {
	
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		
//		write() ;
		read();
	}
	
	//反序列化
	private static void read() throws FileNotFoundException, IOException, ClassNotFoundException {
		
		//创建反序列化流对象
		//public ObjectInputStream(InputStream in)
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("oos.txt")) ;
		
		//读
		//public final Object readObject():从 ObjectInputStream 读取对象。
		Object obj = in.readObject() ;
		
		in.close();
		System.out.println(obj);//Person [name=高圆圆, age=27]
	}

	
	//序列化
	private static void write() throws FileNotFoundException, IOException {
		
		//创建一个序列化流对象
		//public ObjectOutputStream(OutputStream out)
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt")) ;
		
		//创建一个Person类对象
		Person p = new Person("高圆圆", 27) ;
		
		//public final void writeObject(Object obj)
		oos.writeObject(p);
		
		//关闭资源
		oos.close();
		
	}
}

Properties:表示了一个持久的属性集(简称:属性集合类)  extends Hashtable<K,V> Map集合的
 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

 public Properties():无参构造

public class PropertiesDemo {
	
	public static void main(String[] args) {
		
		//它继承Hashtable
		//创建一个属性集合类对象
//		Properties<String,String> prop = new Properties<String,String>() ;
		Properties prop = new Properties() ;
		System.out.println(prop);
		System.out.println("---------------------");
		
		//给属性集合类中的属性列表添加元素
		prop.put("高圆圆", "赵又廷") ;
		prop.put("文章", "马伊琍") ;
		prop.put("黄晓明", "baby") ;
		
		System.out.println(prop);
		
		//遍历属性集合类
		Set<Object> keySet = prop.keySet() ;
		for(Object key :keySet) {
			Object value = prop.get(key) ;
			System.out.println(key+"="+value);
		}
	}
}//{}
//---------------------
//{高圆圆=赵又廷, 黄晓明=baby, 文章=马伊琍}
//高圆圆=赵又廷
//黄晓明=baby
//文章=马伊琍
属性集合类的特有功能:
  public Object setProperty(String key, String value) :给属性列表中添加键和值,并且强制都使用String
  public Set<String> stringPropertyNames():遍历的功能
public String getProperty(String key)用指定的键在此属性列表中搜索属性
public class PropertiesDemo2 {
	
	public static void main(String[] args) {
		
		//创建属性集合类对象
		Properties prop = new Properties() ;
		
		//添加元素
		prop.setProperty("张三", "20") ;
		prop.setProperty("李四", "22") ;
		prop.setProperty("王五", "18") ;
		
		//遍历
		//获取所有的键的集合
		Set<String> keyset = prop.stringPropertyNames() ;
		for(String key:keyset) {
			//通过键找值
			String value = prop.getProperty(key) ;
			System.out.println(key+"----"+value);
		}
	}
}//王五----18
//张三----20
//李四----22

可保存在流中或从流中加载,只能使用属性集合类
public void store(Writer writer,String comments):把集合中的数据保存文本文件中(属性集合)
 public void load(Reader reader):将文本文件中的数据加载到属性集合中

举例:
打游戏:游戏进度的保存和游戏加载

public class PropertiesDemo3 {
	
	public static void main(String[] args) throws IOException {
		
//		MyStore();
		MyLoad();
	}
	
	//将文本文件中的数据加载属性集合类中
	private static void MyLoad() throws IOException {
		
		//创建属性集合类对象
		Properties prop =new Properties() ;
		
		//public void load(Reader reader):将文本文件中的数据加载到属性集合中
		FileReader fr = new FileReader("prop.txt") ;
		//加载
		prop.load(fr);
		fr.close();
		System.out.println(prop);
		
	}
	
	//将属性集合中的数据保存到文本文件中
	private static void MyStore() throws IOException {
		
		//创建一个属性集合类对象
		Properties prop = new Properties() ;
		
		//添加元素
		prop.setProperty("张三", "20") ;
		prop.setProperty("文章", "29") ;
		prop.setProperty("成龙", "55") ;
		
		//public void store(Writer writer,String comments):把集合中的数据保存文本文件中(属性集合)
		FileWriter fw = new FileWriter("name.txt") ;
		//将数据保存到文本文件中
		prop.store(fw, "names'content");
		
		//释放资源
		fw.close();
 		
	}
}
控制台输出:{zhangsan=30, lisi=40, wangwu=45}
name.txt文件中写入#names'content
#Sun May 20 11:14:30 CST 2018
成龙=55
张三=20
文章=29


  我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。
  请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100
  
  1)读取文件的内容,将文件内容加载属性集合类中
  2)遍历属性集合,获取所有的键的集合
  3)遍历的键的时候,可以判断是否有"lisi"这样一个键
  4)有的话,就更改
  5)需要将当前属性集合类中的保存文本文件中
public class PropertiesTest {
	
	public static void main(String[] args) throws IOException {
		
		//创建属性集合类对象
		Properties prop = new Properties() ;
		
		//读取文本文件内容加载到集合中
		FileReader fr = new FileReader("user.txt") ;
		prop.load(fr); 
		fr.close(); 
		
		//遍历属性集合
		//获取所有的键的集合
		Set<String> keySet = prop.stringPropertyNames() ;
		for(String key:keySet) {
			//判断
			if("lisi".equals(key)) {
				//更改
				prop.setProperty(key, "100") ;
			}
		}
		
		//将属性集合中的数据保存文本文件中
		FileWriter fw = new FileWriter("user.txt") ;
		prop.store(fw, "content");
		fw.close();

	}
}
需求:
 我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,
  超过5次提示:游戏试玩已结束,请付费。

import java.util.Scanner;

public class GetNumber {
	
	private GetNumber() {
		
	}
	
	//为了防止打断点的时候,黄色警告线会影响断点,所有加入强制解决
	@SuppressWarnings("resource")
	public static void start() {
		//1-100随机数
		int number = (int) (Math.random()*100+1) ;
		
		//定义一个统计变量
		int count = 0 ;
		
		while(true) {
			
			
			Scanner sc = new Scanner(System.in) ;
			System.out.println("请输入要猜的数据:");
			int guessNumber = sc.nextInt() ;
			
			count ++ ;
			if(guessNumber>number) {
				System.out.println("你要猜的数据大了...");
			}else if(guessNumber <number) {
				System.out.println("你要猜的数据小了...");
			}else {
				System.out.println("恭喜您"+count+"次猜中了...");
				break ;
			}
			
		}
	}
}
public class PropertiesTest2 {
	
	public static void main(String[] args) throws IOException {
		
		//创建文件
		/*File file = new File("content.txt") ;
		if(file!=null) {
			file.createNewFile() ;
		}*/
		
		//将文件的内容加载到属性集合中
		Properties prop = new Properties() ;
		//创建字符输入流
		FileReader fr = new FileReader("count.txt") ;
		prop.load(fr);
		fr.close();
		
		//现在有内容了,通过键获取当前对应的值(String)
		String value = prop.getProperty("count") ;
		
		//String---int
		int number = Integer.parseInt(value) ;
		//判断
		//超过5次提示:游戏试玩已结束,请付费。
		if(number >5) {
			System.out.println("游戏试玩接收,请您付费...");
			System.exit(0);
		}else {
			number ++ ;
			prop.setProperty("count", String.valueOf(number)) ;
			FileWriter fw = new FileWriter("count.txt") ;
			prop.store(fw, "game'content");
			fw.close() ;
			
			GetNumber.start();
			
		}
	}
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值