首先得了解一下IO流是指什么,以及能够做什么?
我们在一开始使用java中的scanner类中的时候,就会使用到system.in表示是由键盘输入,当我们拿到数据后,又调用system.out将数据输出,这就是一个比较基础的输出和输入的过程,而当中就涉及到了我们的IO流,I代表Input,O代表Output,这样就可以理解IO流是什么
流(stream),是我们描述数据传送的一种概念,只能操作输入或者输出中的一种,不能同时兼备两个功能,如果需要,那创建两个流
按照IO流的分类方式分为3种:
1.数据类型:字节流(byte)、字符流(char)
2.流向:输入流(in),输出流(out)
3.流的功能:节点流(node)和过滤流(filter)
我们先讲解按数据类型中的字节流和字符流
字节流一般用于处理图像、视频、音频等类型的文件,而字符流一般就处理.txt的文本文件,字节流能处理所有的文件,但是字符流只能处理.txt文件
这是IO流中的关系图,像Inputstream和Outputstream就是后面类的父类,下面的字符流中的Reader和Writer也是如此。
一般而言,我们操作文件的数据相对来说会多一点,我们就拿子类的FileInputStream和FileOutputstream来操作
import java.io.FileInputStream;
import java.io.IOException;
public class Allthemain {
public static void main(String[] args) throws IOException {
//给定文件的路径
String filepath = "D:\\develop_tool\\1.txt";
//调用文件处理的IO
FileInputStream fileInputStream = new FileInputStream(filepath);
byte[] by = new byte[1024]; //定义字节数组存储文件中的数据
StringBuilder sb = new StringBuilder(); //拿到的数据是ASCALL码,我们将其转换为String类型
int length ; //拿到字节数组存放数据的长度
while((length= fileInputStream.read(by))!= -1){
sb.append(new String(by,0,length));
}
System.out.println(sb);
fileInputStream.close();
}
}
得到结果
这样我们就可以在文件中获取到数据了,这是调用FileInputStream,下面我们调取FileOutputstream,因为我们写入的数据也是需要UTF-8的编码格式,所以我们需要修改一下
public class Allthemain {
public static void main(String[] args) throws IOException {
//给定文件的路径
String filepath = "D:\\develop_tool\\1.txt";
//调用文件处理的IO
FileOutputStream fileOutputStream = new FileOutputStream(filepath);
String str = "my name is demo";
byte[] by = new byte[1024]; //定义字节数组存储文件中的数据
fileOutputStream.write(str.getBytes());
fileOutputStream.close();
}
}
我们执行成功后,在文档中确实是可以拿到这样的数据的
但是现在新的问题出现了,那就是我们之前的数据被覆盖掉了。其实这里很简单,我们在方法中点进去查看这个类就会看到这样的
FileOutputstream中是有第二个参数,传入一个布尔值,true就表示追加,没有给就不追加,这样我们的覆盖追加问题也可以解决掉。
接下来我们讲的是BufferedInputSream和BufferedOutputstream两种字节缓冲流,我们在刚刚的输入流中,因为我们写的东西比较小,所以看不出来,速度的问题,其实如果文件大一点,速度就会相当的慢,因为是一个一个的读,当中放入字节数组后,会稍微快一点,不过我们更推荐使用缓冲流的做法。缓冲流就算为解决字节流的速度缓慢问题而生,不过其实底层也是InputStream和Outputstream来起作用,唯一不同的点是,缓冲流是放入缓存中,一次性进行读取或写入,相对一个一个的来说,这是毋庸置疑要快的。
public class Allthemain {
public static void main(String[] args) throws IOException {
//给定文件的路径
String filepath = "D:\\develop_tool\\1.txt";
//调用文件处理的IO
BufferedInputStream BI = new BufferedInputStream(new FileInputStream(filepath));
BufferedOutputStream BO = new BufferedOutputStream(new FileOutputStream(filepath,true));
String str = "my name is demo2";
BO.write(str.getBytes()); //写入str
byte[] by = new byte[1024];
int length;
StringBuilder sb = new StringBuilder();
while((length = BI.read(by)) != -1){
sb.append(new String(by,0,length));
}
System.out.println(sb);
BI.close();
BO.close();
}
}
我直接两步一起操作了,要不然太慢了,结果也是正确的
这样我们就掌握了字节流
下面我们开始讲解字符流InputStreamReader和OutputstreamWriter两种字符流,他们也可以简写为FileWriter和FileReader,名字虽然不同,不过既然是简写,两者的作用是相同的
字符流的好处在于,我们写入数据时,是不需要调用当中的getByte()转换的,并且我们读取数据通常要采用数组的方式读取,但是读取这个为字符串,我们将上方的byte[]改为char[],改为字符的。
public class Allthemain {
public static void main(String[] args) throws IOException {
//给定文件的路径
String filepath = "D:\\develop_tool\\1.txt";
//调用文件处理的IO
FileWriter fw = new FileWriter(filepath,true);
FileReader fr = new FileReader(filepath);
String str = "my name is demo3";
fw.write(str); //写入str
char[] by = new char[1024];
int length;
StringBuilder sb = new StringBuilder();
while((length = fr.read(by)) != -1){
sb.append(new String(by,0,length));
}
System.out.println(sb);
fw.close();
fr.close();
}
}
得到结果
这样我们就可以得到由字符流的写入和输出
接下来我们使用字符缓冲流BufferedReader和BufferedWriter两种缓冲流
public class Allthemain {
public static void main(String[] args) throws IOException {
//给定文件的路径
String filepath = "D:\\develop_tool\\1.txt";
//调用文件处理的IO
BufferedWriter fw = new BufferedWriter(new FileWriter(filepath,true));
BufferedReader fr = new BufferedReader(new FileReader(filepath));
String str = "my name is demo4";
fw.write(str); //写入str
char[] by = new char[1024];
int length;
StringBuilder sb = new StringBuilder();
while((length = fr.read(by)) != -1){
sb.append(new String(by,0,length));
}
System.out.println(sb);
fw.close();
fr.close();
}
}
得到结果
这样我们就了解输入输出流对文件的操作,要注意的是,在输入操作中,我们可能还没来的及看到数据,就可以使用flush()刷新方法,这样就可以在输出流中拿到数据,但也不用担心没有输出,因为本身调用close的时候就会刷新一次,close是用来关闭流和释放相关的所有系统资源
因为我写入的数据比较小,看不出来哪个方法是要快一点还是慢一点,不过我们可以使用System.currentTimeMillis()这个方法来作差,比较哪个的速度是最快的,不过缓冲流的设计已经很快了,使用缓冲流就OK的,不过面试的时候得讲出来字节流和字符流的区别,还有速度问题。