目录
1.3.1 对象序列化流:ObjectOutputStream:
1.3.2 对象反序列化流:ObjectInputStream
1.3.3 serialVersionUID&transient
思维导图
1 标准输入输出流
System类中有两个静态的成员变量:
● public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一输入源
● public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
标准输入流:
public class Test {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符串:");
String line = br.readLine();
System.out.println(line);
System.out.println("请输入一个整数:");
int num =Integer.parseInt(br.readLine()) ;
System.out.println(num);
//因为自己使用键盘输入操作过于麻烦,所以Java给我们提供了一个工具类Scanner,用于键盘输入
Scanner sc = new Scanner(System.in);
}
}
标准输出流:
public class SystemOutDemo {
public static void main(String[] args) {
//public static final PrintStream out:标准输出流
PrintStream ps = System.out;
//能够方便地打印各种数据值
// ps.print("hello");
// ps.print(100);
// ps.println("hello");
// ps.println(100);
//System.out的本质是一个字节输出流
System.out.println("hello");
System.out.println(100);
System.out.println();
// System.out.print();
}
}
输出语句的本质:是一个标准的输出流
● PrintStream ps = System.out;
● PrintStream类有的方法,System.out都可以使用
1.2 打印流
打印流分类:
● 字节打印流: PrintStream
● 字符打印流: PrintWriter
打印流特点:
● 只负责输出数据,不负责读取数据
● 有自己的特有方法
字节打印流
● PrintStream(String fileName):使用指定的文件名创建新的打印流
● 使用继承父类的方法写数据,查看的时候会转码(如:ps.write(97),查看相关文档显示的会是a),使用字节的特有方法写数据,查看的数据会原样输出
示例代码:
public class Test02 {
public static void main(String[] args) throws IOException {
PrintStream ps = new PrintStream("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\ps.txt");
ps.write(97);
ps.println();
ps.println(98);
ps.println(99);
ps.close();
}
}
字符打印流
构造方法:
示例代码:
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
//PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
// PrintWriter pw = new PrintWriter("myOtherStream\\pw.txt");
// pw.write("hello");
// pw.write("\r\n");
// pw.flush();
// pw.write("world");
// pw.write("\r\n");
// pw.flush();
// pw.println("hello");
/*
pw.write("hello");
pw.write("\r\n");
*/
// pw.flush();
// pw.println("world");
// pw.flush();
//PrintWriter(Writer out, boolean autoFlush):创建一个新的PrintWriter
PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),true);
// PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),false);
pw.println("hello");
/*
pw.write("hello");
pw.write("\r\n");
pw.flush();
*/
pw.println("world");
pw.close();
}
}
案例:复制Java文件(打印流改进)
示例代码:
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\src\\com\\mysystem\\test01\\Test02.java"));
PrintWriter pw = new PrintWriter(new FileWriter("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\pw.java"),true);
String line;
while ((line = br.readLine()) != null){
pw.println(line);
}
br.close();
pw.close();
}
}
1.3 对象序列化流
序列化:把内存中的对象转换为字节序列的过程(简单来说就是把对象转化成二进制)。目的是为了保存或者网络传输
反序列化:就是把字节序列转化成对象
要实现序列化和反序列化,就要使用对象序列化流和对象反序列化流
● 对象序列化流:ObjectOutputStream
● 对象反序列化流:ObjectInputStream
1.3.1 对象序列化流:ObjectOutputStream:
● 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
ObjectOutputStream(OutputStream out) | 创建一个写入指定的OutputStream的ObjectOutputStream |
序列化对象的方法
void WriteObject(Object obj) | 将指定的对象写入ObjectOutputStream |
示例代码:
//学生类
package com.mysystem.test03;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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;
}
}
//测试类(序列化)
package com.mysystem.test03;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class Test {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\oos.txt"));
Student s = new Student("张三",20);
oos.writeObject(s);
oos.close();
}
}
补充:序列化时,对象必须继承于Serializable接口,否则运行时将会报错
序列化接口仅仅是标识接口,没有方法需要重现。目的是为了让我们看见一个类如果继承于它,那么表示这个类可以被序列化
1.3.2 对象反序列化流:ObjectInputStream
构造方法:
ObjectOutputStream(OutputStream out) | 创建一个写入指定的OutputStream的ObjectOutputStream |
序列化对象方法:
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream |
示例代码:
package com.mysystem.test03;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Test02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\oos.txt"));
Object obj = ois.readObject();
Student s = (Student)obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
1.3.3 serialVersionUID&transient
serialVersionUID
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
● 会出问题,会抛出InvalidClassException异常
如果出问题了,如何解决呢?
● 重新序列化
给对象所属的类加一个serialVersionUID
● private static final long serialVersionUID = 42L;
transient
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
● 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
2 Properties集合
2.1 概述:
● 是一个Map体系的集合类
● Properties可以保存到流中或者从流中加载
练习:Properties作为Map集合的使用
示例代码:
public class Test {
public static void main(String[] args) {
Properties ppt = new Properties();
ppt.put("001","张三");
ppt.put("002","李四");
ppt.put("003","王五");
Set<Object> keySet = ppt.keySet();
for (Object key : keySet){
Object value = ppt.get(key);
System.out.println(key + "," + value);
}
}
}
2.2 Properties作为集合特有的方法
示例代码:
public class Test02 {
public static void main(String[] args) {
Properties ppt = new Properties();
ppt.setProperty("001","张三");
ppt.setProperty("002","李四");
ppt.setProperty("003","王五");
Set<String> names = ppt.stringPropertyNames();
for (String key : names){
String value = ppt.getProperty(key);
System.out.println(key + "," +value);
}
}
}
2.3 Properties和IO流相结合的方法
示例代码:
public class Test03 {
public static void main(String[] args) throws IOException{
//myStore();
myLoad();
}
private static void myLoad() throws IOException{
Properties prop = new Properties();
FileReader fr = new FileReader("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore()throws IOException {
Properties prop = new Properties();
prop.setProperty("001","张三");
prop.setProperty("002","李四");
prop.setProperty("003","王五");
FileWriter fw = new FileWriter("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\fw.txt");
prop.store(fw,null);
fw.close();
}
}
案例:游戏次数
//游戏类
package com.mysystem.test04;
import java.util.Random;
import java.util.Scanner;
public class GuessNumber {
public GuessNumber() {
}
public static void start() {
Random r = new Random();
int num = r.nextInt(100) + 1;
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你猜的数字:");
int n = sc.nextInt();
if (n < num) {
System.out.println("你输入的数字" + n + "小了");
} else if (n > num) {
System.out.println("你输入的数字" + n + "大了");
} else {
System.out.println("恭喜你!猜对了!");
break;
}
}
}
}
//测试类
package com.mysystem.test04;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class Test04 {
public static void main(String[] args) throws IOException {
//创建Properties集合,存储游戏次数
Properties prop = new Properties();
//加载load()方法需要一个File file的参数,创建fr,读取数据
FileReader fr = new FileReader("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\game.txt");
//将fr读到的数据存入Properties集合中
prop.load(fr);
//释放资源
fr.close();
//根据键count获取值
String count = prop.getProperty("count");
int num = Integer.parseInt(count);
if (num >= 3){
System.out.println("游戏试玩已结束!想玩请继续充值!(www.it.cn)");
}else {
//玩游戏,调用游戏类
GuessNumber.start();
//玩一次就改变值
num++;
//将改变的值重新写入count键对应的值中
prop.setProperty("count",String.valueOf(num));
FileWriter fw = new FileWriter("E:\\JavaTXT\\Task\\IO流\\myOtherStream\\game.txt");
prop.store(fw,null);
fw.close();
}
}
}