概述
IO流:文件与程序之间数据的传输
IO流的输入与输出是通过程序作为参考
IO划分
按方向划分:输入流与输出流
输入流:从文件中读取数据到程序
输出流:从程序中写出数据到文件
按单位划分:字节流与字符流
字节流:一个字节一个字节的读写;读写效率低,但可以读写所有的文件
字符流:一个字符一个字符的读写;读写效率高,但只能读写文本文件;不能读写二进制文件(音频,图片,视频)
按功能划分:节点流与处理流
节点流:没有经过包装的最原生的流
处理流:经过包装后,功能更为强大的流
字节流
流都是分开的,有输入流和输出流两个类
字节流最大的类为OutputStream/InputStream(抽象类)
应用:实例化子类对象来进行操作,且有很多场景下直接使用面向对象来操作流,因为需要使用子类独有方法
字节节点流
文件输入输出流FileOutputStream/FileInputStream:是一个字节节点流
public class caogao {
@Test
public void Output() throws Exception{
//创建字节节点流
OutputStream os = new FileOutputStream("tst1");
//输入内容
os.write("hello".getBytes());
//释放资源
os.close();
}
@Test
public void Input() throws Exception{
//创建字节节点流
InputStream is = new FileInputStream("tst1");
//读取内容
byte [] b = new byte[1024];
int len = is.read(b);//读取数据,并放到b数组,返回长度;如果结束,则返回-1
while (len != -1) {
System.out.println(new String(b, 0, len));
len =is.read(b);
}
//释放资源
is.close();
}
}
字节缓冲流
字节缓冲流:BufferedOutputStream/BufferedInputStream,父类是FilterOutputStream,爷爷类是OutputStream
字节缓冲流是处理流,包装了节点流后生成的缓冲流字节缓冲流:里面带了缓冲区,存取数据都需要先经过缓冲区;
缓冲区满或刷新缓冲区,内容才会到磁盘文件
好处:减少了与磁盘交互次数,提升了性能
内部提供的缓冲区大小为8192个(恒定值)字节,如果未超出范围,都在缓冲区中
设计模式:装饰者模式,针对组织结构的设计
@Test //写
public void outTest() throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
bos.write("helloworld..缓冲流".getBytes()); //写到缓冲区
//bos.flush(); //刷新缓冲区
bos.close(); //刷新缓冲区+关闭资源
}
@Test //读
public void inTest() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
byte[] b = new byte[1024];
int len = bis.read(b);
System.out.println(new String(b, 0,len));
bis.close();
}
对象流
ObjectOutputStream对象流:用于读写对象的流; 写的过程则是序列化(加密);读的过程则是反序列化(解密)
//Serializable 标记型接口,没有抽象方法
class Person implements Serializable{ //实现序列化接口
/*transient*/ String name; //transient,static:都是不参与序列化的关键字
int age;
public Person(String name,int age) {
this.name=name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Test2 {
@Test //对象流的写
public void outTest() throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
//oos.writeObject("zs");
//存自定义对象
//也可以通过集合写和读多个对象,并存储到对象流
oos.writeObject(new Person("zs", 30));
oos.writeObject(new Person("ls", 20)); //存多个对象
oos.writeObject(new Person("ww", 25));
oos.close();
}
@Test //对象流的读
public void inTest() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
//String o = (String) ois.readObject();
Object o = null;
try {
while(true) {
System.out.println(ois.readObject()); //取多个对象
}
} catch (Exception e) {
}finally {
ois.close();
}
}
}
字符流
字符流的抽象类为Writer/Reader,其他字符流都是它的子类
字符节点流
FileWriter/FileReader: 在字符流里面,字符节点流是最简单的流;
应用上及自身设计都很简单,如果只是简单的读写,则可用字符节点流
为什么设计简单?因为该类全部靠继承而来; 字符流都可以直接存储字符串
@Test
public void outTest() throws IOException {
//查看内部实现可知,字符流都是通过字节流转换而来
FileWriter fw = new FileWriter("a.txt");
fw.write("hello,filewriter..");
fw.close();
}
@Test
public void inTest() throws IOException {
FileReader fr = new FileReader("a.txt");
char[] cbuf = new char[1024];
int len = fr.read(cbuf);
//char[]转String
System.out.println(new String(cbuf,0,len));
fr.close();
}
字符缓冲流
类似字节缓冲流,减少了与磁盘交互的次数,提高了性能
字符缓冲流中提供了两个常用的方法:换行读和写
@Test
public void outTest() throws IOException {
//字符缓冲流:包装字符节点流得到的缓冲流
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
for(int i=1;i<=5;i++) {
bw.write("好好学习,天天向上..."+i);
bw.newLine(); //换行
}
bw.close();
}
@Test
public void inTest() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String msg = null; //换行读取,如果读到文件末尾则返回null
while((msg = br.readLine())!=null) {
System.out.println(msg);
}
br.close();
}
字符转换流
字符转换流OutputStreamWriter: 可以将字节流转换为字符流; 同时可设置字符的编码方式
@Test
public void outTest() throws IOException {
//字符节点流FileWriter的父类OutputStreamWriter
//中文乱码问题:当写的编码和读的编码不一致,则会出现乱码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),"utf-8");
osw.write("hello,转换流"); //将数据以utf-8编码方式写到文件
osw.close();
}
@Test
public void inTest() throws IOException {
InputStreamReader isw = new InputStreamReader(new FileInputStream("a.txt"),"utf-8");
char[] cbuf = new char[1024];
int len = isw.read(cbuf);
System.out.println(new String(cbuf,0,len));
isw.close();
}
//应用场景:直接从字节流转换到字符缓冲流,如何转? ---转换流
@Test
public void bufferTest() throws IOException {
OutputStream os = new FileOutputStream("a.txt");
//通过封装转换流,可以得到字符缓冲流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("helloworld..."); //字符缓冲流提升性能,且可换行读写功能
bw.close();
}
IO汇总
写法整理
字节流:以stream结尾
抽象类:OutputStream/InputStream
字节节点流:FileOutputStream/FileInputStream
字节缓冲流:BuferedOutputStream/BufferedInputStream
对象流: ObjectOutputStream/ObjectInputStream
字符流: 以Writer/Reader结尾
抽象类:Writer/Reader
字符节点流:FileWriter/FileReader
字符缓冲流:BufferedWriter/BufferedReader
字符输出流:PrintWriter
字符转换流:OutputStreamWriter/InputStreamReader
应用场景
数据量小的内容拷贝使用字节节点流,例如图片拷贝; 只是拷贝简单文本内容则使用字符节点流
读写内容较大的二进制,且需要考虑性能则使用字节缓冲流; 非二进制或读写换行则用字符缓冲流
从字节流转字符流,或需要乱码处理,则使用转换流;
读写对象内容,则使用对象流;
简单的换行打印输出,则使用输出流;
结论:常用的流--字节节点流,字节缓冲流,字符缓冲流