目录
Buffered字符处理流(BufferedReader和BufferedWriter):
Buffered字节处理流(BufferedInputStream和BufferedOutputStream) :
ObjectOutputStream和ObjectInputStream:
介绍
在Java中的流,还分为字节流和处理流
节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
2.处理流(也叫包装流)是“连接"在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter
看下图:
节点流就是通过不同的方式去访问不同的数据源 ,比如文件就用文件流访问,数组就用数组流访问。
而包装流就是将这些节点流进行整合包装,提供一个更为完整的读写功能体系。
具体包装流是如何实现的,这就涉及到了一种涉及模式:拟修饰器设计模式。
具体不好描述,看视频 BV15B4y1u7Rn P12节。
Buffered处理流:
Buffered字符处理流(BufferedReader和BufferedWriter):
BufferedReader 和BufferedWriter属于字符流,是按照字符来读取数据的
关闭时,只需要关闭外层流即可
BufferedReader:
可以引用所有的Read子类,包括文件、数组、管道等
这里读取了story.txt文件,里面存放了之前使用输入输出流copy文件的代码
package com.io.reader;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* @author 华子
* bufferedReader的使用
*/
public class BufReader {
public static void main(String[] args) throws Exception {
String filePath = "e:\\story.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = " ";
while((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}
这里还可以进行按行读取。
运行结果:
BufferedrWriter:
它同样也可以引用Writer里的所有子类。
package com.io.writer;
import java.io.BufferedWriter;
import java.io.FileWriter;
/**
* @author 华子
* bufferedWriter的使用
*/
public class BufWriter {
public static void main(String[] args) throws Exception{
String filePath = "e:\\ok.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("Hello,郑仲华");
bufferedWriter.newLine();
bufferedWriter.write("Hello,郑仲华");
bufferedWriter.newLine();
bufferedWriter.write("Hello,郑仲华");
bufferedWriter.newLine();
bufferedWriter.close();
}
}
很简单的代码,创建一个文件,写入数据 。(实现了换行nextLine)
案例:
BufferedReader和BufferedWriter拷贝文本文件:
package com.io.writer;
import java.io.*;
/**
* @author 华子
* 使用BufferedReader和BufferedWtriter进行文件拷贝
*/
public class BufCopy {
public static void main(String[] args) throws Exception{
String filePath01 = "e:\\story.txt";
String filePath02 = "d:\\news.txt";
String line = "";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath01));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath02));
while ((line = bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
System.out.println("拷贝成功...");
if(bufferedReader!=null){
bufferedReader.close();
}
if(bufferedWriter!=null){
bufferedWriter.close();
}
}
}
因为这两兄弟属于字符流,无法读取二进制文件(图片,视频,音乐等)
Buffered字节处理流(BufferedInputStream和BufferedOutputStream) :
用法和字符处理流类似。
案例:
使用BufferedInputStream和BufferedOutputStream拷贝二进制文件:
package com.io.outputstream_;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author 华子
* BufferedInputStream和BufferedOutputStream拷贝二进制文件(图片、视频、音乐)
* 字节流BufferedInputStream和BufferedOutputStream也可以用于操作文本文件
*/
public class BufCopy02 {
public static void main(String[] args) throws Exception{
String srcFilePath = "e:\\demo.mp4";
String destFilePath = "d:\\demo.mp4";
int readLen = 0;
byte[] buf = new byte[1024];
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
while((readLen = bufferedInputStream.read(buf))!=-1){
bufferedOutputStream.write(buf,0,readLen);
}
System.out.println("拷贝成功...");
if (bufferedInputStream != null){
bufferedInputStream.close();
}
if (bufferedOutputStream != null){
bufferedOutputStream.close();
}
}
}
对象处理流:
再看处理流之前,首先要搞懂两个概念。
序列化和反序列化:
1.序列化就是在保存数据时, 保存数据的值和数据类型
2.反序列化就是在恢复数据时,恢复数据的值和数据类型
3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
类必须实现如下两个接口之一 :Serializable(是一个标记接口)或者Externalizable。
大多数情况下都使用第一种接口,因为第二种接口需要实现方法。
大概图解:
接下来就是两种对象处理流:
ObjectOutputStream和ObjectInputStream:
ObjectOutputStream 提供序列化功能
ObjectInputStream 提供反序列化功能
看代码:
ObjectOutputStream(序列化):
package com.io.outputstream_;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* ObjectOutputStream 序列化数据
*/
public class ObjOutputStream {
public static void main(String[] args) throws IOException {
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
// 序列化数据
oos.writeInt(100);//这里实现了自动装箱 int -->Integer(实现了Serializable)
oos.writeBoolean(true);//boolean-->Boolean(实现了Serializable)
oos.writeChar('a');//char-->Char(实现了Serializable)
oos.writeDouble(9.5);//double-->Double(实现了Serializable)
oos.writeUTF("芝麻干");//String类型序列化
oos.writeObject(new Dog("阿黄",3));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
写入数据(序列化数据)后,会生成一个.dat文件。
ObjectOutputStream(反序列化):
package com.io.inputSteam;
import com.io.outputstream_.Dog;
import java.io.FileInputStream;;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @author 华子
* ObjectInputStream实现数据反序列化
*/
public class ObjInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath = "e:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
// 读取(反序列化)的顺序要和你保存的数据(序列化)的顺序一直
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
// dog的编译类型是Object,运行类型是Dog
Object dog = ois.readObject();
System.out.println("运行类型:"+dog.getClass());
System.out.println(dog);
// 如果要引用Dog的方法,需要向下转型
Dog dog1 = (Dog)dog;
System.out.println(dog1.getName());
ois.close();
}
}
读取数据(反序列化)
运行结果:
对象处理流细节总结:
对象处理流有很多细节,在这里总结一下:
1)读写顺序要一致
2)要求实现序列化或反序列化对象,需要实现Serializable
3)序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
5)序列化对象时,要求里面属性的类型也需要实现序列化接口
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化