节点流和处理流【包装流】
基本介绍:
节点流只能指对某种特定的数据源读写数据,就是如果使用FileReader
只能操作文件,不像包装流可以传入Reader
的子类
包装流中BufferedReader
或BufferedWriter
两个类中分别含有一个private Reader in
或private Writer out
,说明可以包装Reader
或Writer
类的子类
包装流使用了一种修饰模式
节点流和处理流【包装流】一览图
节点流和处理流的区别和联系
- 节点流是底层、低级流,直接跟数据源相接
- 处理流【包装流】包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方式来完成输入输出。
- 处理流【包装流】对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要体现以下两个方面:
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可以提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
模拟修饰器设计模式
package IO_.modification;
/**
* @author: 海康
* @version: 1.0
*/
public abstract class Reader_ {
public void fileReader(){ }
public void StringReader(){ }
}
package IO_.modification;
/**
* @author: 海康
* @version: 1.0
*/
public class FileReader_ extends Reader_{
public void fileReader(){
System.out.println("读取字符流");
}
}
package IO_.modification;
/**
* @author: 海康
* @version: 1.0
*/
public class StringReader_ extends Reader_{
public void StringReader(){
System.out.println("读取字符串");
}
}
package IO_.modification;
/**
* @author: 海康
* @version: 1.0
*/
public class BufferedReader_ extends Reader_{
private Reader_ reader_;
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
// 进行扩展了 批量处理FileReader
public void fileReader(int num){
for (int i = 0; i < num; i++) {
reader_.fileReader();
}
}
// 进行扩展了 批量处理StringReader
public void StringReader(int num){
for (int i = 0; i < num; i++) {
reader_.StringReader();
}
}
}
package IO_.modification;
import java.io.BufferedReader;
/**
* @author: 海康
* @version: 1.0
*/
public class Test {
public static void main(String[] args) {
BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_());
bufferedReader_1.StringReader(10);
bufferedReader_.fileReader(5);
}
}
处理流-BufferedReader
类 和 BufferedWriter
类都处理字符的
BufferedReader
类
继承关系图:
构造器
Constructor and Description |
---|
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。 |
BufferedReader(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流。 |
常用方法:
Modifier and Type | Method and Description |
---|---|
void | close() 关闭流并释放与之相关联的任何系统资源。 |
int | read() 读一个字符 |
int | read(char[] cbuf, int off, int len) 将字符读入数组的一部分。 |
String | readLine() 读一行文字。当返回null时说明读取完毕 |
readLine()
方法读取的内容是一行,但是不会读取换行符,所以在写入不换行,全在一行上
注意是:关闭时处理流,只需要关闭外层流即可,底层动态绑定关闭的是传入处理对象
package IO_.reader_;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author: 海康
* @version: 1.0
*/
public class BufferedReader1 {
public static void main(String[] args) {
}
@Test
public void readerFile(){
String filePath = "e:\\IDEACODE\\javase\\story.txt";
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(filePath);
bufferedReader = new BufferedReader(fileReader);
// 使用是 read(char[] ch)来读取
// int length = 0;
// char[] ch = new char[1024*8];
// while ((length=bufferedReader.read(ch))!=-1){
// System.out.print(new String(ch,0,length));
// }
// 使用 readLine() 来读取每次都是一整行一整行读取
String line = "";
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// 在使用包装流时,只需要关闭外层流即可
if (bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.hspedu.reader_;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* 演示bufferedReader 使用
*/
public class BufferedReader_ {
public static void main(String[] args) throws Exception {
String filePath = "e:\\a.java";
//创建bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line; //按行读取, 效率高
//说明
//1. bufferedReader.readLine() 是按行读取文件
//2. 当返回null 时,表示文件读取完毕
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
//关闭流, 这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流
//FileReader。
/*
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();//in 就是我们传入的 new FileReader(filePath), 关闭了.
} finally {
in = null;
cb = null;
}
}
}
*/
bufferedReader.close();
}
}
BufferedWriter
类
构造器:
Constructor and Description |
---|
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。 |
BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。 |
常用方法:
Modifier and Type | Method and Description |
---|---|
void | close() 关闭流,先刷新。 |
void | flush() 刷新流。 |
void | newLine() 写一行行分隔符。 |
void | write(char[] cbuf, int off, int len) 写入字符数组的一部分。 |
void | write(int c) 写一个字符 |
void | write(String s, int off, int len) 写一个字符串的一部分。 |
应用案例:
使用BufferedWriter将“海康湛江广州南宁西安杭州”,写入到文件中
package IO_.writer_;
import org.junit.jupiter.api.Test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author: 海康
* @version: 1.0
*/
public class BufferedWriter1 {
public static void main(String[] args) {
}
@Test
public void writerFile(){
String writerPath = "e:\\IDEACODE\\javase\\story.txt";
BufferedWriter bufferedWriter = null;
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(writerPath,true);
bufferedWriter = new BufferedWriter(fileWriter);
String writerContext = "海康湛江广州南宁西安杭州";
bufferedWriter.write(writerContext);
bufferedWriter.newLine();// 一般建议插入一个换行符,否则会全写在一行上
System.out.println("写入成功!!!");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedWriter!=null){
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在关闭时,只需要关闭外层流即可
bufferedWriter.newLine();// 一般建议插入一个换行符,否则会全写在一行上
BufferedReader
和BufferedWriter
是对字符进行操作的,不要去操作二进制文件,可能造成文件损坏 ,二进制文件有音频,视频 ,图片等
综合案例
使用BufferedReader和BufferedWriter完全文本文件拷贝,注意文件编码
package IO_.writer_;
import java.io.*;
/**
* @author: 海康
* @version: 1.0
*/
public class BufferedCopy {
public static void main(String[] args) {
String readerPath = "e:\\IDEACODE\\javase\\story.txt";
String writerPath = "e:\\IDEACODE\\javase\\new.txt";
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(readerPath));
writer = new BufferedWriter(new FileWriter(writerPath,true));
// 按 char[] 方式读取和写入
// char[] ch = new char[1024*8];
// int length = 0;
// while ((length = reader.read(ch))!=-1){
// writer.write(ch,0,length);
// }
// 使用换行的方式进行读取和写入
String line= "";
while ((line=reader.readLine())!=null){
writer.write(line);
// 注意是由于reader.readLine()读取是不读取换行符,所以在写入时,一定要写入换行符
writer.newLine();// 否则全写在一行上
}
System.out.println("拷贝完成!!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 在使用流完成后一定关闭流,释放资源 只需要关闭外层流即可
if (reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.hspedu.writer_;
import java.io.*;
public class BufferedCopy_ {
public static void main(String[] args) {
//老韩说明
//1. BufferedReader 和 BufferedWriter 是安装字符操作
//2. 不要去操作 二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏
//BufferedInputStream
//BufferedOutputStream
String srcFilePath = "e:\\a.java";
String destFilePath = "e:\\a2.java";
// String srcFilePath = "e:\\0245_基础学Java_引出this.avi";
// String destFilePath = "e:\\a2.avi";
BufferedReader br = null;
BufferedWriter bw = null;
String line;
try {
br = new BufferedReader(new FileReader(srcFilePath));
bw = new BufferedWriter(new FileWriter(destFilePath));
//说明: readLine 读取一行内容,但是没有换行
while ((line = br.readLine()) != null) {
//每读取一行,就写入
bw.write(line);
//插入一个换行
bw.newLine();
}
System.out.println("拷贝完毕...");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(br != null) {
br.close();
}
if(bw != null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedInputStream
和 BufferedOutPutStrream
类都是处理字节的
BufferedInputStream
类
基本介绍:
BufferedInputStream
是字节流,在创建BufferedInputStream
时,会创建一个内部缓冲数组
继承关系图:
构造器
Constructor and Description |
---|
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,输入流 in ,供以后使用。 |
BufferedInputStream(InputStream in, int size) 创建 BufferedInputStream 具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。 |
常用方法:
Modifier and Type | Method and Description |
---|---|
void | close() 关闭此输入流并释放与流相关联的任何系统资源。 |
int | read() 见 read 法 InputStream 的一般合同。 |
int | read(byte[] b, int off, int len) 从给定的偏移开始,将字节输入流中的字节读入指定的字节数组。 |
void | reset() 见 reset 法 InputStream 的一般合同。 |
BuferedOutputStream
类
基本介绍:
BufferedOutputStream
是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统中
继承关系:
构造器:
Constructor and Description |
---|
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 |
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。 |
常用方法:
Modifier and Type | Method and Description |
---|---|
void | flush() 刷新缓冲输出流。 |
void | write(byte[] b, int off, int len) 从指定的字节数组写入 len 个字节,从偏移 off 开始到缓冲的输出流。 |
void | write(int b) 将指定的字节写入缓冲的输出流。 |
应用案例:
要求:编程完成图片,音乐的拷贝(要求使用Buffered...流)
package IO_.writer_;
import java.io.*;
/**
* @author: 海康
* @version: 1.0
*/
public class BufferedCopy2 {
public static void main(String[] args) {
String srcCopy = "e:\\rose.jpg";
String doesCopy = "d:\\myRose.jpg";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(srcCopy));
bos = new BufferedOutputStream(new FileOutputStream(doesCopy));
int length = 0;
byte[] ch = new byte[1024*8];
while ((length = bis.read(ch))!=-1){
bos.write(ch,0,length);
}
System.out.println("拷贝完成!!!");
} catch (IOException e) {
e.printStackTrace();
}finally {
// 在使用完流一定要关闭流,在包装流关闭外层流即可
if (bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.hspedu.outputstream_;
import java.io.*;
/**
* 演示使用BufferedOutputStream 和 BufferedInputStream使用
* 使用他们,可以完成二进制文件拷贝.
* 思考:字节流可以操作二进制文件,可以操作文本文件吗?当然可以
*/
public class BufferedCopy02 {
public static void main(String[] args) {
// String srcFilePath = "e:\\Koala.jpg";
// String destFilePath = "e:\\hsp.jpg";
// String srcFilePath = "e:\\0245_零基础学Java_引出this.avi";
// String destFilePath = "e:\\hsp.avi";
String srcFilePath = "e:\\a.java";
String destFilePath = "e:\\a3.java";
//创建BufferedOutputStream对象BufferedInputStream对象
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//因为 FileInputStream 是 InputStream 子类
bis = new BufferedInputStream(new FileInputStream(srcFilePath));
bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
//循环的读取文件,并写入到 destFilePath
byte[] buff = new byte[1024];
int readLen = 0;
//当返回 -1 时,就表示文件读取完毕
while ((readLen = bis.read(buff)) != -1) {
bos.write(buff, 0, readLen);
}
System.out.println("文件拷贝完毕~~~");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
try {
if(bis != null) {
bis.close();
}
if(bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流可以操作文本文件和二进制文件,就是字节流可以操作字符文本