学习目录
一、节点流和处理流
1.基本介绍
节点流:可以从一个特定的数据源读写数据,如FileReader、FileWriter。
处理流:也叫包装流,是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
节点流(绿)和处理流(红)一览表:
2.两者的区别和联系
- 节点流是底层流/低级流,直接根据数据源相接
- 处理流(包装流)包装其其节点流,既可以消除不同节点流的实现差异 ,也可以提供更方便的方法来完成输入输出
- 处理流也叫包装流对节点流进行包装,使用了修饰设计模式,不会直接与数据源相连(底层是模拟修饰器设计模式)
3.处理流功能体现
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可能提供一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
下面通过简单的代码模拟说明处理流(会有种醍醐灌顶的感觉)
模拟一下底层处理流的设计模式(修饰器设计模式)
public class test {
public static void main(String[] args) {
BufferedReader_ bufferedReader_1 = new BufferedReader_(new FileReader_());
bufferedReader_1.readFile();
System.out.println("===============");
bufferedReader_1.readFiles(5);
BufferedReader_ bufferedReader_2 = new BufferedReader_(new StringReader_());
System.out.println("===============");
bufferedReader_2.readStrings(5);
}
}
/**
* 定义一个抽象类,放两个抽象方法
*/
abstract class Reader_ {
public void readFile(){}
public void readString(){}
}
/**
* 模拟一个读文件的节点流
*/
class FileReader_ extends Reader_{
@Override
public void readFile() {
System.out.println("对文件进行读取");
}
}
/**
* 模拟一个读字符串的节点流
*/
class StringReader_ extends Reader_{
@Override
public void readString() {
System.out.println("对字符串进行读取");
}
}
/**
* 模拟一个包装类,实现多个功能
*/
class BufferedReader_ extends Reader_{
private Reader_ reader_; //属性为Reader_类型
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
//读取一次文件,读取字符串同类
public void readFile(){ //相当于封装一层
reader_.readFile();
}
//让方法更加灵活,多次读取文件
public void readFiles(int num){
for (int i = 0; i < num; i++) {
reader_.readFile();
}
}
public void readStrings(int num){
for (int i = 0; i < num; i++) {
reader_.readString();
}
}
}
以上代码也可以进行优化,用多态的动态绑定机制
public class test {
public static void main(String[] args) {
BufferedReader_ bufferedReader_1 = new BufferedReader_(new FileReader_());
bufferedReader_1.read();
bufferedReader_1.reads(5);
BufferedReader_ bufferedReader_2 = new BufferedReader_(new StringReader_());
bufferedReader_2.read();
bufferedReader_2.reads(5);
}
}
/**
* 定义一个抽象类,放两个抽象方法
*/
abstract class Reader_ {
public abstract void read();
}
/**
* 模拟一个读文件的节点流
*/
class FileReader_ extends Reader_{
@Override
public void read() {
System.out.println("对文件进行读取");
}
}
/**
* 模拟一个读字符串的节点流
*/
class StringReader_ extends Reader_{
@Override
public void read() {
System.out.println("对字符串进行读取");
}
}
/**
* 模拟一个包装类,实现多个功能
*/
class BufferedReader_{
private Reader_ reader_; //属性为Reader_类型
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
public void read(){
reader_.read();
}
//让方法更加灵活,多次读取
public void reads(int num){
for (int i = 0; i < num; i++) {
reader_.read();
}
}
}
二、包装流BufferedReader和BufferedWriter
BufferedReader和BufferedWriter均为字符处理流,关闭流时只需要关闭外层流即可,不可以处理二进制文件(如:音频、视频)
1.BufferedReader
基本介绍
BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,具体方法的详细使用请看API
快速入门
读取一个文本文件,并把读取内容输出到控制台上
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class test {
public static void main(String[] args) throws IOException {
String path = "F:\\test.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
String line = null;
//按行读取,效率高,readLine方法没有换行功能
//当读到流的末尾,则返回为null
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
//这里只需要关闭BufferedReader流即可,底层代码会自动关闭FileReader
if(bufferedReader != null){
bufferedReader.close();
}
}
}
2.BufferedWriter
基本介绍
BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,具体方法的详细使用请看API
快速入门
将内容写入一个文本文件中
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class test {
public static void main(String[] args) throws IOException {
String path = "F:\\test1.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path)); //覆盖的形式
// BufferedWriter bufferedWriter1 = new BufferedWriter(new FileWriter(path,true)); //追加的形式
//注意,这里不会换行
bufferedWriter.write("你好java");
bufferedWriter.newLine(); //插入换行
bufferedWriter.write("你好scala");
bufferedWriter.newLine(); //插入换行
bufferedWriter.write("你好python");
//关闭流,FileWriter也会关闭
if (bufferedWriter !=null){
bufferedWriter.close();
}
}
}
3.综合小案例-复制
import java.io.*;
public class test {
public static void main(String[] args) throws IOException {
String path = "F:\\test1.txt";
String path1 = "F:\\test2.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path1));
String line = null;
while ((line = bufferedReader.readLine()) != null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
if(bufferedReader != null){
bufferedReader.close();
}
if (bufferedWriter !=null){
bufferedWriter.close();
}
}
}
二、包装流BufferedOutputStream和BufferedInputStream
这里是引用BufferedOutputStream和BufferedInputStream均为自己处理流,关闭流时只需要关闭外层流即可,既可以处理二进制文件又可以处理文本文件
BufferedOutputStream和BufferedInputStream具体方法使用和上面差不多,具体方法的使用请看API
1.综合小案例-复制
import java.io.*;
public class test {
public static void main(String[] args) throws IOException {
String path = "F:\\java.jpeg";
String path1 = "F:\\java1.jpeg";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
//FileInputStream是InputStream的子类,所有可以作为BufferedInputStream的参数;
//BufferedOutputStream同理
bis = new BufferedInputStream(new FileInputStream(path));
bos = new BufferedOutputStream(new FileOutputStream(path1));
byte[] bytes = new byte[1024]; //每次读取的大小
int readlen = 0;
//bis.read(bytes)返回类型为int,返回-1时,表示文件读取完毕
while ((readlen = bis.read(bytes)) != -1){
bos.write(bytes,0,readlen);
}
//关闭BufferedInputStream和BufferedOutputStream即可
//FileInputStream和FileOutputStream会自动关闭
if (bis != null){
bis.close();
}
if (bos != null){
bos.close();
}
}
}
下面代码和上面功能一样,只是把异常用try/catch包起来了
import java.io.*;
public class test {
public static void main(String[] args) {
String path = "F:\\java.jpeg";
String path1 = "F:\\java1.jpeg";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(path));
bos = new BufferedOutputStream(new FileOutputStream(path1));
byte[] bytes = new byte[1024]; //每次读取的大小
int readlen = 0;
//bis.read(bytes)返回类型为int,返回-1时,表示文件读取完毕
while ((readlen = bis.read(bytes)) != -1){
bos.write(bytes,0,readlen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null){
bis.close();
}
if (bos != null){
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}