java重要基础操作之-------------Io操作(字符流、序列化、反序列化笔记)

199 阅读3分钟

今天我们来聊聊IO操作之-----------------字符流

Reader和Writer它们都是抽象类,所以要使用它们的子类 InputStreamReader和OutputStreamWriter

1.OutputStreamWriter

继承关系

用字符流向文件中写入数据

public class TestWrite {
	public static void main(String[] args) throws Exception {
		//创建流对象
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\hello.txt",true));
		//准备数据
		String s = "1208早上好";
		//写数据
		osw.write(s);
		//关闭资源
		osw.close();
	}
}

2.InputStreamReader

继承关系

public class TestRead {
	public static void main(String[] args) throws Exception {
		InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\hello.txt"));
		int r = 0;
		while(-1 != (r = isr.read())) {
			System.out.println((char)r);
		}
		isr.close();
	}
}

3.字节转字符流(编码格式)

4.复制文本文件,使用字符流不能复制非文本文件

此方法效率特别低

public class TestCopy {
	public static void main(String[] args) throws Exception {
		InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\j.png"));
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:\\j.png"));
		int r = 0;
		while(-1 != (r = isr.read())) {
			osw.write(r);
		}
		osw.close();
		isr.close();
	}
}

高效率的复制文本文件(重要)

示例代码:

//高效率复制文本文件
public class TestCopy2 {
	public static void main(String[] args) throws Exception {
		InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\hello.txt"));
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:\\hello.txt"));
		char[] cbuf = new char[1024];
		int len = 0;
		while(-1 != (len = isr.read(cbuf))) {
			osw.write(cbuf, 0, len);
		}
		osw.close();
		isr.close();
	}
}

5.缓冲流

使用缓冲流复制文本文件 内部也是字符数组,内部进行读写时也要相互转化,所以效率没直接定义字符数组存取效率高。

示例代码

public class TestCopy3 {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("d:\\hello.txt")));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:\\hello.txt")));
		String line = null;
		while(null != (line = br.readLine())) {
			bw.write(line);
			bw.newLine();//表示和系统相关的换行符
		}
		bw.close();
		br.close();
	}
}

6.序列化与反序列化

序列化:把对象保存在硬盘中,使用ObjectOutputStream其中的writeObject方法

ObjectOutputStream继承关系:

反序列化:把对象从硬盘中读取出来,使用ObjectInputStream其中的readObject方法

ObjectInputStream继承关系:

序列化对象之前必须让实体类实现Serializable接口

Serializable接口既没有属性,也没有方法,我们把这种接口称为标志性接口

1.将对象序列化到内存中

public class TestWriteObject {
	public static void main(String[] args) throws Exception {
		//java要求,如果想让一个类被序列化,需要让该类实现Serializable接口
		//Serializable接口既没有属性,也没有方法,我们把这种接口称为标志性接口
		Dog dog = new Dog("旺财", 2, "黑色");
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\dog.txt"));
		oos.writeObject(dog);/ere/一次只能写入一个对象,如果想写入多个对象需要放到集合中
		oos.close();
	}
}

2.把对象从硬盘中反序列化到内存中

public class TestReadObject {
	public static void main(String[] args) throws Exception {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\dog.txt"));
		Dog dog = (Dog) ois.readObject();//读取对象,返回值类型是Object类型,需要向下类型转换
		System.out.println(dog);
		ois.close();
	}
}

特别注意:如果修改了序列化对象对应类的结构,就不能反序列化了

原理:当序列化时会根据类的结构计算一个值UID,当反序列化时又会计算一个UID值,拿两个值进行比较,如果一致可以成功反序列化,否则不能反序列化

在实体类的属性前手动生成UID

private static final long serialVersionUID = 1L;

如果不希望某些数据被反序列化,可以添加transient关键字

private transient String color;

3.将集合序列化到硬盘中

public class TestWriteBook {
	public static void main(String[] args) throws Exception {
		ArrayList<Book> books = new ArrayList<Book>();
		books.add(new Book("java大全1", "张老师1", 8001));
		books.add(new Book("java大全2", "张老师2", 8002));
		books.add(new Book("java大全3", "张老师3", 8003));
		
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\books.txt"));
		oos.writeObject(books);
		oos.close();
	}
}

public class TestReadBook {
	public static void main(String[] args) throws Exception {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\books.txt"));
		ArrayList<Book> books = (ArrayList<Book>) ois.readObject();
		System.out.println(books);
		ois.close();
	}
}

7.使用BufferedReader替代Scanner

System.in标准的输入流,可以把键盘的数据保存在流中

System.out标准的打印流,可以把流中的数据输出到屏幕上

可以使用BufferedReader替代Scanner

示例代码:

public class TestRead4 {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入姓名");
		String name = br.readLine();
		System.out.println("name=" + name);
		br.close();
	}
}

Io字符流就介绍这么多了,对字符流其他方法操作还不太熟练的小可爱们,可以看看官方API文档

记得点赞+关注👉: 本人github地址:github.com/Lmobject