对象处理流
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型。
- 反序列化就是在恢复数据时,恢复数据的值和数据类型。
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable //这是一个标记接口,没有方法。
- Externalizable //该接口有方法需要实现,因此我们一般实现上面Serializable 接口。
ObjectInputStream和ObjectOutputStream
- 功能:提供了对基本类型或对象类型的序列化和反序列化的方法。
- ObjectOutputStream提供序列化功能。
- ObjectInputStream提供反序列化功能。
示例:
package com.study.srv.demo17;
import java.io.Serializable;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 14:33
* 创建一个公共类
*/
public class Test implements Serializable {
private String name;
private int age;
public Test(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;
}
@Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.study.srv.demo17;
import java.io.*;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 11:09
* 演示ObjectOutputStream的使用,完成数据的序列化
*/
public class Demo14 {
public static void main(String []args) throws IOException {
//序列化文件地址,保存的文件格式,不是文本格式而是按照自己格式保存。
String src="E:\\t.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(src));
//int类型自动——>Integer(Integer类实现了Serializable)
oos.writeInt(12);
//double类型自动——>Double(Double类实现了Serializable)
oos.writeDouble(3.14);
//boolean类型自动——>Boolean(Boolean类实现了Serializable)
oos.writeBoolean(false);
//char类型自动——>Character(Character类实现了Serializable)
oos.writeChar('s');
//String(Integer类实现了Serializable)
oos.writeUTF("无聊");
//如果想保存一个对象,要让对象实现Serializable接口
oos.writeObject(new Test("测试",16));
//关闭处理流
oos.close();
System.out.println("数据按照序列化保存完毕");
}
}
package com.study.srv.demo17;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 12:03
* 演示ObjectInputStream的使用,完成数据的反序列化
*/
public class Demo15 {
public static void main(String[] args) throws IOException {
//反序列化文件
String src="E:\\t.dat";
//创建ObjectInputStream对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(src));
//读取(反序列化)数据顺序时,顺序需要与保存(序列化)数据保持一致。
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readUTF());
try {
//object的编译类型时Object,object的运行类型是Test
Object object = ois.readObject();
System.out.println("运行类型="+object.getClass());
System.out.println("Test信息="+object);
//如果要调用Test中的方法,需要向下转型。
//则我们需要将Test类的定义,转移到可以引用的位置(设成公共类)
Test test=(Test)object;
System.out.println(test.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//关闭处理流
ois.close();
}
}
注意事项
- 读写顺序必须一致。
- 要求实现序列化或反序列化对象,需要实现Serializable。
- 序列化的类中建议添加SerialVerisonUID,为了提高版本兼容性。
- 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员。
- 序列化对象时,要求里面属性的类型也需要实现序列化接口。
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。
package com.study.srv.demo17;
import java.io.Serializable;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 14:33
* 创建一个公共类
*/
public class Test implements Serializable {
private String name;
private int age;
/**
* 序列化对象时,默认将里面所有属性都进行序列化,但是除了static或transient修饰的成员。
*/
private static String sex;
private transient String nation;
/**
* 串行版本uid,序列化的版本号,可以提高兼容性。
*/
private static final Long serialVersionUID=1L;
public Test(String name, int age,String sex,String nation) {
this.name = name;
this.age = age;
Test.sex =sex;
this.nation=nation;
}
@Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", age=" + age +
", nation='" + nation + '\'' +
", sex='" + sex +'\'' +
'}';
}
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;
}
}
序列化对象时,默认将里面所有属性都进行序列化,但是除了static或transient修饰的成员。
/** * 序列化对象时,要求里面属性的类型也要实现序列化接口 */ private Test2 test2=new Test2();
所以要将属性类型也实现序列化接口。
标准输入输出流
标准 | 编译类型 | 运行类型 | 默认设备 |
System.in 标准输入 | InputStream | BufferedInputStream | 键盘 |
System.out 标准输出 | PrintStream | PrintStream | 显示器 |
package com.study.srv.demo17;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 16:02
*/
public class Demo16 {
public static void main(String[] args) {
//System.in的编译类型是InputStream,运行类型为BufferedInputStream
//表示标准键盘输入 键盘
InputStream in = System.in;
System.out.println("运行类型="+in.getClass());
//传统用法,Scanner从标准输入键盘接收数据
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
//System.out的编译类型是PrintStream,运行类型为PrintStream
//表示标准键盘输出 显示器
PrintStream out = System.out;
System.out.println("运行类型="+out.getClass());
//传统用法,System.out.println
System.out.println(num);
}
}
转换流
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)。
- OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)。
- 当处理纯文本数据时,如果使用字符效率更高,并且可以有效解决中文问题,所以建议将字节流转换为字符流。
- 可以在使用指定编码格式(比如utf-8,gbk,gb2312,ISO8859-1等)。
package com.study.srv.demo17;
import java.io.*;
import java.io.FileReader;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/4 18:00
* 中文乱码
* 使用InputStreamReader转换流解决中文乱码
* 将字节流FileInputStream转换成字符流InputStreamReader,指定编码gbk/utf-8
*/
public class Demo17 {
public static void main(String[] args) throws IOException {
//读取e:\\c.txt 文件到程序
String src="e:\\c.txt";
//默认情况下,读取文件是按照utf-8格式进行编码的
//1.转换FileInputStream字节流为InputStreamReader字符流
//2.指定编码格式为GBK
//InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(src),"GBK");
//将InputStreamReader 传入BufferedReader
//BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//也可以直接套用
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(src),"GBK"));
String num;
while ((num=bufferedReader.readLine())!=null){
System.out.println(num);
}
//关闭外层处理流
bufferedReader.close();
}
}
package com.study.srv.demo17;
import java.io.*;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/5 16:46
* 演示OutputStreamWriter使用
* 把FileOutputStream字节流转换为OutputStreamWriter
*/
public class Demo18 {
public static void main(String[] args) throws IOException {
//读取e:\\c.txt 文件到程序
String src="e:\\c.txt";
String path="E:\\css.txt";
String charSet="utf-8";
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(src),"GBK"));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path),charSet);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
String num;
while ((num=bufferedReader.readLine())!=null){
bufferedWriter.write(num);
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}
打印流
打印流只有输出流,没有输入流:PrintStream、PrintWriter
PrintStream
package com.study.srv.demo17;
import java.io.IOException;
import java.io.PrintStream;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/5 17:37
*/
public class Demo19 {
public static void main(String[] args) throws IOException {
PrintStream printStream=System.out;
//默认情况下,PrintStream输出数据的位置是 标准输出,即显示器
printStream.print("测试一下");
/*
底层机制为
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
*/
printStream.write("测试一下".getBytes());
printStream.close();
//可以修改打印流输出的位置/设备
//打印到E:\ss.txt里
System.setOut(new PrintStream("E:\\ss.txt"));
System.out.println("还是测试");
}
}
PrintWriter
package com.study.srv.demo17;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/6 10:37
*/
public class Demo20 {
public static void main(String[] args) throws IOException {
PrintWriter printWriter=new PrintWriter(System.out);
printWriter.print("测试");
printWriter.close();
//也可以修改打印输出路径
PrintWriter printWriter1 = new PrintWriter(new FileWriter("E:\\sc.txt"));
printWriter1.print("最终测试");
printWriter1.close();
}
}
在PrintWriter中修改打印输出路径,打印流必须要关闭,否则默认数据被清除,但打印流的数据需要关闭流之后才会写入到文件中。
Properties类
package com.study.srv.demo17;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/6 10:50
* 操作properties文件
*/
public class Demo21 {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("src/com/study/srv/demo17/mysql.properties"));
String line;
while ((line=bufferedReader.readLine())!=null){
String[] split = line.split("=");
if (split[0].equals("ip")) {
System.out.println(split[0] + "的值是:" + split[1]);
}
}
bufferedReader.close();
}
}
可以看出有普通的流对于properties文件操作过于繁琐,同样也无法保证数据的正确性,所以需要用专门的properties类操作properties文件。
基本介绍
- 专门用来读取配置文件的集合类,并且对配置文件格式有严格要求
配置文件格式:
键=值
键=值
- 键值对不需要有空格,值不需要用引号一起来。默认类型是String。
- Properties类的常见方法
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象(存在修改,不存在添加)
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储unicode码
package com.study.srv.demo17;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/6 11:25
* 演示Properties
*/
public class Demo22 {
public static void main(String[] args) throws IOException {
//1.先创建Properties对象
Properties properties = new Properties();
//2.加载指定配置文件
properties.load(new FileReader("src/com/study/srv/demo17/mysql.properties"));
//3.把k-v显示出来
properties.list(System.out);
//4.根据键找到值
String ip = properties.getProperty("ip");
System.out.println("ip是:"+ip);
}
}
package com.study.srv.demo17;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Properties;
/**
* @author Wen先森
* @version 1.0
* @date 2022/7/6 11:38
* Properties类创建和修改配置文件
*/
public class Demo23 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
//创建
//1.如果文件已经有key,就是修改
//2.如果文件没有可以,就是创建
properties.setProperty("userName","测试");
properties.setProperty("userPwd","123456");
//将k-v存储到文件中
//store(Writer writer, String comments)中的comments是注释,可以填入null,也可以写入注释
//使用FileWriter字符流写入,中文也会直接写入
properties.store(new FileWriter("src/com/study/srv/demo17/sql.properties"),"设置sql连接");
//使用FileOutputStream字节流写入,中文会转为unicode写入
//properties.store(new FileOutputStream("src/com/study/srv/demo17/sql.properties"),"设置sql连接");
}
}