java中的IO流是实现输入,输出的基础,他可以方便的实现数据的输入/输出,在java中把不同的输入/输出源抽象为流,通过流的方式,允许java程序以相同的方式来访问不同的输入/输出源,javaIO体系复杂是由于在基础的节点流上使用装饰着模式生成了一些功能更加强大的处理流,这样做的好处是降低了代码的耦合性,但是作为代价就是让不少初学者认为io体系复杂,很容易混淆,但是我们把他归类之后其实也就那么几类,下面让我们对应下图,慢慢了解。
1.由上图可以看出,所有的流都是基于InputSttream,OutputStream,Reader,Writer是个抽象的基础类
2.其中InputStream/Reader是输入流的抽象基类,其中前者是字节流,后者是字符流(输入流:只能从中读取数据,不能向其中写入数据)
3.OutputStream/Writer是输出流的抽象基类,其中前者是字节流,后者是字符流(输出路:只能向其中写入数据,不能从其中读取数据)
4.InputStream中定义了
int read():从输入流中读取单个字节,并返回读取的字节数据(字节数据可以直接转为int类型)
int read(byte[] b):从输入流中读取b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数
int read(byte[] b,int off,int len):从输入流中读取len个字节的数据并将其存储在字节数组b中,放入数组b时,并不是从数组起点开始,而是从off开始,返回实际读取的字节数据
5.Reader中定义了
int read():从输入流中读取单个字符,并返回读取的字符数据(字符数据可以直接转为int类型)
int read(char[] cbuf):从输入流中最多读取cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字符数
int read(char[] cbuf,int off,int len):从输入流中读取len个字符数据的并将其存储在字节数组cufb中,放入数组时,并不是从数组起点开始,而是从off开始,返回实际读取的字节数据
6.OutputStream和Writer,两个流都提供了如下上方法
void write(int c):将指定的字节/字符输出到输出流中,其中c既可以代表字节,也可以代表字符
void write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定的输出流中
void write(byte[]/char[] buf,int off,int len):将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到指定的输出流中
有因为字符流可以直接以字符作为操作单位,所以Writer可以用字符串来代替字符数组,即以String 作为参数。Writer中还包含一下连个方法。
void write(String str):将str字符串里面包含的字符输出到指定的输出流中
void write(String str,int off,int len):将str字符串里从off开始,长度为len的字符输出到指定的输出流中
7. 节点流:直接与底层的IO设备,文件交互的流,eg:FileInputStream,ByteArrayOutputStream,ObjectInputStream等
处理流:包装节点流的加强流,所有的处理流都是直接以IO节点流作为构造参数,eg:BufferedInputStream,BufferedWriter等
java体系结构在InputStream,OutputStream,Reader,Writer四个基础抽象流的基础上,实现了用于访问文件,访问数组,访问管道,访问字符串的一系列基本流,也叫节点流(再设计模式中叫做具体组件)。利用基本的节点流我们便可以操作所有IO功能。但是为了效率,java又为我们提供了一些使用的处理流,用于包装节点流,生成新的流。(装饰着设计模式的思想:装饰者(处理流)与被装饰者(节点流)实现相同的借口或实现同一抽象类,将被装饰者(节点流)作为参数传递给装饰他的类(处理流)的构造函数,那么装饰者(处理流)就有了与被装饰(节点流)着相同的方法,调用装饰者(处理流)的方法,底层实际上调用的是被装饰者(节点流)的方法,已有java实现,这样做的优势是在不修改java源码的情况下,装饰者(处理流)可以在调用被装饰者(节点流)方法的前后,做一些功能的扩展,从而实现增强 )。如果有时间的话,可能会将设计模式的原理和实现方式发表一下。
package com.test.myio;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class IoTest {
public static void main(String[] args) {
try {
//节点流(操作文件)/被装饰者
FileInputStream inputStream = new FileInputStream(new File("test.txt"));
//处理流(包装节点流)/装饰者,装饰节点流
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
int len=0;
byte [] b=new byte[1024];
while((len=bufferedInputStream.read(b))!=-1){
System.out.println(new String(b,0,len));
}
//只需关闭上层处理流,节点流就会关闭;
bufferedInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
8.装换流
输入/输出体系中还提供了连个转换流,InputStreamReader,OutputStreamReader,其中InputStreamReader可以将字节输入流转换为字符输入流,OutputStreamWriter可以将字节输出流转换为字符输出流。
package com.test.myio;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class ConvertIO {
public static void main(String[] args) throws IOException {
//创建字节输入流
FileInputStream fileInputStream = new FileInputStream("test.txt");
//转换为字符输入流
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");
//包装为缓冲流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line=null;
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}