Java中的高级I/O流-缓冲流、数据流以及对象流
前言:通过前面的学习,已经学完了Java中的基本流;Java中的流有字节流和字符流两大类,而每一种流都有对应的输入和输出流;
1、字节流
1.1字节输入流-主要是:FileInputStream
1.2字节输出流-主要是:FileOutputStream
2、字符流
2.1字符输入流-主要是:FileReader
2.2字符输出流-主要是:FileWriter
无论是字节或者字符输入流都有三种主要的read()方法,分别是读单字节/字符read()方法 利用字节/字符数组进行读 read(byte [ ] bytes) 为了防止最后一次读入有误,我们一般会指定每次字节/字符数组的读入read(byte [ ] bytes,int start int len)
那么相对应的无论字节或者是字符输出流都有一种和输入流相对应的写方法,所以写方法也主要有三种,看你是怎么读入进来的,我就怎么写出去;
总结起来,其实就学了两对流(一对字节流,一对字符流),三种读写的方法(单字节/字符读写 字节/字符数组读写 指定位置的字节/字符的读写)
Java中除了基本的I/O流,还有高级的I/O流,那就是缓冲流和包装流(包括数据流和对象流)
一、缓冲流
为什么要有缓冲流?
比如说,家里盖房子,有一堆砖头要搬在工地100米外,单字节的读取就好比你一个人每次搬一块砖头,从堆砖头的地方搬到工地,这样可定很费时间,然后好的方法就是多叫几个小伙伴帮你一起搬砖头,这样因为人多了,每次可以搬十块砖头,但效率还是很低,这就好比我们的字节/字符数组读写操作;然而聪明的人类会用小推车,每次先搬砖头搬到小车上,再利用小推车运到工地上去,这样你或者你的小伙伴们再从小推车上取砖头是不是方便多了呀!这样效率就会大大提高,缓冲流就好比我们的小推车;给砖头暂时提供一个可存放的空间;
注意:缓冲流属于包装流,只能对已有的流进行封装,不能直接关联文件进行操作
二、字节缓冲流
三、字符缓冲流
四、字节和字符缓冲流的使用:使用缓冲流进行文件的拷贝
源代码:
package com.huaxin.zhou;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
public class IOcopy {
public static void main(String[] args) {
IOcopy icopy = new IOcopy();
icopy.copy3();
icopy.copy4();
}
public void copy3() {
try {
//创建字节输入流对象
FileInputStream fis
= new FileInputStream("C:\\Users\\Administrator\\Desktop\\my.doc");
//创建字节输出流对象
FileOutputStream fos
= new FileOutputStream("C:\\Users\\Administrator\\Desktop\\mycopy.doc");
//利用字节缓冲流包装字节输入和输出流
BufferedInputStream bis = new BufferedInputStream(fis,1024);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//从小推车上一个一个取砖头下来
// int value =bis.read();
//
// while( value!=-1){
// bos.write(value);
// bos.flush();
// value =bis.read();
// }
//很多小伙伴一起从小推车上取砖头
byte [] bytes = new byte[10];
int value =bis.read(bytes);
while( value!=-1){
bos.write(bytes,0,value);
bos.flush();
value =bis.read(bytes);
}
//关闭流
bis.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void copy4() {
//构建字符输入流对象
FileReader fr;
try {
fr = new FileReader("C:\\Users\\Administrator\\Desktop\\1.txt");
//构建字符输出流对象
FileWriter fw =
new FileWriter("C:\\Users\\Administrator\\Desktop\\11.txt");
//字符缓冲流对字符输入输出流进行包装
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
//单字节从小推车上取砖头
// int value =br.read();
// while(value!=-1){
// bw.write(value);
// bw.flush();
// value =br.read();
// }
//很多小伙伴们一起取砖头
char [] chars = new char[10];
int value =br.read(chars);
while(value!=-1){
bw.write(chars,0,value);
bw.flush();
value=br.read(chars);
}
//利用readLine方法每次读取一行内容
// String value=br.readLine();
//
//输出单个字符
// while(value!=null){
// bw.write(value);
// bw.flush();
// value=br.readLine();
// }
//关闭流
br.close();
bw.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
五、数据流
分析下面程序的运行结果:
package com.huaxin.IORW;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import sun.reflect.FieldInfo;
public class IOTest {
public static void main(String[] args) {
int a=200;
int b=1000;
try {
FileOutputStream fos =
new FileOutputStream("C:\\Users\\Administrator\\Desktop\\2.txt");
fos.write(a);
fos.write(b);
fos.close();
FileInputStream fis = new
FileInputStream("C:\\Users\\Administrator\\Desktop\\2.txt");
int value1=fis.read();
System.out.println(value1);
int value2=fis.read();
System.out.println(value2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
为什么后面写入的1000读出来变成了232了呢?
因为我们是读出一个字节,一个字节是八位,所以能读出的最大整数值是255;那么怎么把1000读取出来呢?这个时候就要用到数据流了!
数据流的写方法,同样有读方法,参看Java的API 文档
六、对象流
对象流就比较好玩了,当我们在程序中定义了一个学生类,并且想把这个学生类的实例用文件保存起来,有需要的时候再读取这个学生的信息;对象流就是解决这样的问题,可以把类类型的数据永久的保存起来;
对象流的使用:
Student类:
package com.huaxin.IORW;
import java.io.Serializable;
public class Student implements Serializable{
String name;
int age;
public Student(){
}
public Student(String name,int age){
this.name=name;
this.age=age;
}
}
测试类:
package com.huaxin.IORW;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectTest {
public static void main(String[] args) {
//创建两个学生对象
Student stu1 = new Student("张三",20);
Student stu2 = new Student("流浪洲",21);
try {
//构建输出流
FileOutputStream fos = new
FileOutputStream("C:\\Users\\Administrator\\Desktop\\3.txt");
//利用对象输出流包装输出流
ObjectOutputStream oos =new ObjectOutputStream(fos);
//写出对象
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
//创建输入流
FileInputStream fis = new
FileInputStream("C:\\Users\\Administrator\\Desktop\\3.txt");
//对象输入流包装输入流
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象,并强制转型为Student类型
Student stu11=(Student)ois.readObject();
System.out.println(stu11.name+":"+stu11.age);
Student stu22=(Student)ois.readObject();
System.out.println(stu22.name+":"+stu22.age);
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用特殊协议保存起来的对象
需要注意的是:进行序列化时,切记所有相关的类要时间Serializable接口
总结:
1、Java中的高级流主要有缓冲流(包括字节和字符缓冲流)、数据流、对象流
2、弄明白其中的原理,这些流都解决了什么样的问题?那个缓冲里那里,得好好理解,一开始我以为我理解了,其实并没有,想明白利用字节数组进行读以及缓冲流进行读的区别;
3、以前对对象流觉得很不好理解,现在学明白了,才发现对象流原来大有用处呀!
4、学无止境,一起共勉!