java_day16_IO、序列化
一、IO流
IO流划分
IO流【输入输出流】:
按照流向划分:
输入流:外部数据 -> java程序
输出流:java程序 -> 外部数据
按照数据类型划分【根据使用记事本打开是否能够看懂来决定】
字节流【万能流】:
字节输入流:
InputStream【抽象类】
- FileInputStream【实现子类】【普通字节输入流】
- BufferedInputStream【字节缓冲输入流】
字节输出流:
OutputStream【抽象类】
- FileOutputStream【实现子类】【普通字节输出流】
- BufferedOutputStream【字节缓冲输出流】
字符流:
字符输入流:
Reader【抽象类】
- InputStreamReader【具体实现子类】【普通字符输入流】
- FileReader【继承自InputStreamReader】
- BufferedReader 【字符缓冲输入流】
字符输出流:
Writer【抽象类】
- OutputStreamWriter【具体实现子类】【普通字符输出流】
- FileWriter【继承自OutputStreamWriter】
- BufferedWriter【字符缓冲输出流】
一、字节流
1、字节输入流
普通字节输入流
字节流【万能流】:
字节输入流:
InputStream(抽象类)
- FileInputStream(实现子类)
FileInputStream:
构造方法:
FileInputStream(File file)
FileInputStream(String name)
成员方法:
public int read()
public int read(byte[] b)
代码案例:
public class FileInputStreamDemo1 {
public static void main(String[] args) throws Exception {
// FileInputStream fis = new FileInputStream(new File("java/src/com/shujia/day16/a1.txt"));
FileInputStream fis = new FileInputStream("java/src/com/shujia/day16/a1.txt");
//public int read() 一次只读取一个字节
// 如果没有读到数据,返回-1
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// System.out.print((char)fis.read());
// int i = 0;
// while ((i = fis.read()) != -1) {
// System.out.print((char) i);
// }
//public int read(byte[] b) 一次读取一个字节数组
//创建一个字节数组,用作接收读取到的字节
byte[] bytes = new byte[7];
int length = 0;
while ((length = fis.read(bytes))!=-1){
//读取到的字节在字节数组中
//返回的是实际读取到的字节数
//将字节数组转字符串
String s = new String(bytes,0,length);
System.out.print(s);
}
// 释放资源
fis.close();
}
}
字节缓冲输入流
InputStream:
FileInputStream【普通的字节输入流】:
BufferedInputStream【字节缓冲输入流】:
代码案例:
public class BufferedInputStreamDemo1 {
public static void main(String[] args) throws Exception {
//BufferedInputStream(InputStream in)
//创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("java/src/com/shujia/day16/a1.txt"));
// 一次读一个字节
// int i = 0;
// while ((i=bis.read())!=-1){
// System.out.print((char) i);
// }
// 一次都一个字节数组
byte[] bytes = new byte[1024];
int length = 0;
while ((length = bis.read(bytes)) != -1) {
String s = new String(bytes, 0, length);
System.out.print(s);
}
//释放资源
bis.close();
}
}
2、字节输出流
普通字节输出流
字节流【万能流】:
字节输出流:
OutputStream(抽象类)
- FileOutputStream(实现子类)
FileOutputStream:
构造方法:
FileOutputStream(File file)
FileOutputStream(String name)
代码案例:
public class FileOutputStreamDemo1 {
public static void main(String[] args) throws Exception{
// FileOutputStream(File file) 将目标文件封装成File对象
// 若目标文件不存在,则会自动创建
// FileOutputStream fos = new FileOutputStream(new File("java/src/com/shujia/day16/a1.txt"));
//FileOutputStream(String name)
FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");
}
}
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)
代码案例:
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws Exception{
// FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");
//public FileOutputStream(String name, boolean append)
FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt", true);
//public void write(int b) 写一个ASCII码值
// fos.write(97);
// public void write(byte[] b) 写一个字节数组到文件中
// byte[] bytes = {97,98,99,100,101,102};
// fos.write(bytes);
//public void write(byte[] b,int index,int len)
// fos.write(bytes,2,3);
fos.write("\r\n".getBytes());
fos.write("李刚真帅!".getBytes());
//释放资源
fos.close();
}
}
字节缓冲输出流
OutputStream:
FileOutputStream【普通的字节输出流】:
BufferedOutputStream【字节缓冲输出流】:
代码案例:
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws Exception{
// FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");
//public FileOutputStream(String name, boolean append)
FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt", true);
//public void write(int b) 写一个ASCII码值
// fos.write(97);
// public void write(byte[] b) 写一个字节数组到文件中
// byte[] bytes = {97,98,99,100,101,102};
// fos.write(bytes);
//public void write(byte[] b,int index,int len)
// fos.write(bytes,2,3);
fos.write("\r\n".getBytes());
fos.write("李刚真帅!".getBytes());
//释放资源
fos.close();
}
}
二、字符流
1、字符输入流
普通字符输入流
字符流:
字符输入流:
Reader【抽象类】
- InputStreamReader【具体实现子类】
- FileReader【继承自InputStreamReader】
InputStreamReader:
构造方法:
InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, String charsetName) 创建一个使用命名字符集的InputStreamReader。
成员方法:
public int read()
public int read(char[] cbuf)
代码案例:
public class InputStreamReaderDemo1 {
public static void main(String[] args) throws Exception {
// InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/a3.txt"));
//InputStreamReader(InputStream in, String charsetName)
InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/a3.txt"), "GBK");
// public int read() 一次都一个字符
// System.out.print((char) isr.read());
// System.out.print((char) isr.read());
// int i = 0;
// while ((i = isr.read()) != -1) {
// System.out.print((char) i);
// }
//public int read(char[] cbuf) 一次读取一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length= isr.read(chars))!=-1){
String s = new String(chars, 0, length);
System.out.print(s);
}
// 释放资源
isr.close();
}
}
用上面的InPutStreamReader创建字符输入流对象,还要传入一个字节输入流对象,挺麻烦的,java还有一个类描述字符输入流,FileReader,使用该类创建字符输入流对象只用传文件地址就行了
FileReader:
字符缓冲输入流
字符输出流:
Writer【抽象类】
- OutputStreamWriter【具体实现子类】
- FileWriter【继承自OutputStreamWriter】
- BufferedWriter【字符缓冲输出流】
BufferedReader 【字符缓冲输入流】:
构造方法:
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
特殊功能:
public String readLine() 一次读取文本文件内容的一行, 不会读取换行符
代码案例:
public class BufferedReaderDemo1 {
public static void main(String[] args) throws Exception {
//创建字符缓冲输入流对象
// BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/b3.txt")));
BufferedReader br = new BufferedReader(new FileReader("java/src/com/shujia/day16/b3.txt"));
//一次读一个字符
// int i = 0;
// while ((i=br.read())!=-1){
// System.out.print((char) i);
// }
//一次读一个字符数组
// char[] chars = new char[1024];
// int length = 0;
// while ((length=br.read(chars))!=-1){
// String s = new String(chars, 0, length);
// System.out.print(s);
// }
//一次读取一行数据
// System.out.println(br.readLine());
// System.out.println(br.readLine());
// System.out.println(br.readLine());
// System.out.println(br.readLine());
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
}
}
2、字符输出流
普通字符输出流
字符输出流:
Writer【抽象类】
- OutputStreamWriter【具体实现子类】
OutputStreamWriter:
构造方法:
OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
成员方法:
public void write(int c)
public void write(char[] cbuf)
public void write(char[] cbuf,int off,int len)
public void write(String str)
public void write(String str,int off,int len)
代码案例:
```plaintext
public class OutputStreamWriterDemo1 {
public static void main(String[] args) throws Exception{
// String s1 = "今天下午放假,不上课!";
//// byte[] bytes = s1.getBytes();
// byte[] bytes = s1.getBytes("GBK");
// System.out.println(Arrays.toString(bytes));
//
// String s = new String(bytes,"GBK");
// System.out.println(s);
// 创建OutputStreamWriter(OutputStream out)对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/a3.txt"),"GBK");
// public void write(int c) 一次写一个字符
// osw.write(97);
// osw.flush();
//public void write(char[] cbuf) 一次写一个字符数组
// char[] chars = {'我','爱','数','加'};
// osw.write(chars);
//public void write(char[] cbuf,int off,int len) 一次写字符数组的一部分
// osw.write(chars,1,3);
// osw.flush();
//public void write(String str) 直接写一个字符串
// osw.write("李刚是32期最帅的男人!");
// osw.flush();
//public void write(String str,int off,int len) 写字符串的一部分
// osw.write("李刚是32期最帅的男人!",6,2);
osw.write("中国");
osw.flush();
//释放资源
osw.close();
}
}
用上面的OutStreamReader创建字符输入流对象,还要传入一个字节输出流对象,挺麻烦的,java还有一个类描述字符输出流,FileWriter,使用该类创建字符输出流对象只用传文件地址就行了
FileWriter:
代码案例:
public class FileWriterDemo1 {
public static void main(String[] args) throws Exception{
//创建字符输出流对象
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/b3.txt"));
// FileWriter fw = new FileWriter("java/src/com/shujia/day16/b2.txt");
//创建字符输入流对象
// InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/b2.txt"));
FileReader fr = new FileReader("java/src/com/shujia/day16/b2.txt");
//一次读一个字符
// int i = 0;
// while ((i = fr.read())!=-1){
// System.out.print((char) i);
// }
//一次读一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length = fr.read(chars))!=-1){
String s = new String(chars, 0, length);
System.out.print(s);
}
// fw.write("今天的天气不错!");
// fw.flush();
fr.close();
// fw.close();
}
}
字符缓冲输出流
字符输出流:
Writer【抽象类】
- OutputStreamWriter【具体实现子类】
- FileWriter【继承自OutputStreamWriter】
- BufferedWriter【字符缓冲输出流】
BufferedWriter【字符缓冲输出流】:
构造方法:
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
特殊方法:
newLine(); // 默认会自动根据当前的系统生成一个换行符
代码案例:
public class BufferedWriterDemo1 {
public static void main(String[] args) throws Exception{
//BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/b3.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("java/src/com/shujia/day16/b3.txt"));
bw.write("落霞与孤鹜齐飞");
// bw.write("\r\n"); // 这里的换行符需要根据将来运行的系统环境来设置
bw.newLine(); // 默认会自动根据当前的系统生成一个换行符
bw.write("秋水共长天一色");
bw.flush();
//释放资源
bw.close();
}
}
二、序列化
序列化:将对象转化成数据流一样在网络中传输
对象输出流:ObjectOutputStream
只有实现了Serializable接口的类的对象才可以进行序列化
反序列化:将网络中数据流还原成一个对象
对象输入流:ObjectInputStream
我们正常写一个对象之后,读取一个对象都是没有问题的。
但是当我们修改了原来的类的时候,再次读取存储的对象就报错了
java.io.InvalidClassException:
com.shujia.day16.Teacher;
local class incompatible:
stream class desc serialVersionUID = -4530247781226673719,
local class serialVersionUID = -4180828856871739850
若不想让某一个成员序列化的话,只需要在该成员前面加上transient关键字
代码案例:
public class ObjectOutputStreamDemo1 {
public static void main(String[] args) throws Exception{
// write();
read();
}
public static void read() throws Exception{
//ObjectInputStream(InputStream in)
//创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("java/src/com/shujia/day16/obj.txt"));
Object o = ois.readObject(); //Object o = new Teacher("小虎", 18)
Teacher t1 = (Teacher)o;
System.out.println(t1);
ois.close();
}
public static void write() throws Exception{
Teacher t1 = new Teacher("小虎", 18);
//创建ObjectOutputStream对象
//ObjectOutputStream(OutputStream out)
//创建一个写入指定的OutputStream的ObjectOutputStream。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("java/src/com/shujia/day16/obj.txt"));
oos.writeObject(t1);
oos.flush();
//释放资源
oos.close();
}
}
三、总结
当一个文件打开能看懂,用字符缓冲流,看不懂用字节缓冲流