什么是IO流?
通过IO来对硬盘的文件进行读和写操作
IO流的分类
1.按照流的方向
以内存作为参照物,将数据拿到内存中来,叫输入(Input)或者叫读(Read)
以内存作为参照物,将内存中的数据取出,叫输出(Output)或者叫写(Write)
2.按照读取数据方式分类
1)按照字节的方式读取数据,称为字节流:
因为计算机中一切数据都是字节数据,也就是说,字节流方式什么文件都能读取。
2)按照字符的方式读取数据,称为字符流:
虽然字节流能读取一切数据,但是字节流只能按二进制来读取文件,用来操作中文的话,不太方便。所以增加字符流:=字节流+编码表
这种流是为了方便读取普通文本文件而存在的。只能读取纯文本文件(能用记事本打开的文件)
注意:不同编码格式所占字节数是不同的。
IO流提供的抽象类
1.1字节流:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
1.2字符流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
2.观察源码发现:
所有流都实现了java.io.Closeable接口,都是可关闭的,都有 close() 方法。
只有输出流实现了java.io.Flushable接口,都是可刷新的,都有 flush() 方法,如果没有flush()可能导致会导致数据丢失
3.在java中只要“类名”以 Stream 结尾的都是字节流。以“ Reader/Writer ”结尾的都是字符流。
io 异常的处理
当IO发生异常时,需要将流关闭,避免资源浪费。
在jdk 1.6版本以前 使用try...catch...finally
代码块,处理异常部分
在jdk 1.7版本以后使用try-with-resource
语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。
格式:
try (创建流对象语句,如果多个流对象语句,使用’;'隔开) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
举例:
public static void main(String[] args) throws IOException {
try(FileInputStream fileInputStream = new FileInputStream("D:/ceshi.txt")) {
int read = fileInputStream.read();
}catch (Exception e){
String message = e.getMessage();
System.out.println(message);
}
}
我们查看它的class文件:最终是转换成了try…catch…finally`的形式来释放资源
public static void main(String[] args) throws IOException {
try {
FileInputStream fileInputStream = new FileInputStream("D:/ceshi.txt");
Throwable var15 = null;
try {
int var3 = fileInputStream.read();
} catch (Throwable var12) {
var15 = var12;
throw var12;
} finally {
if (fileInputStream != null) {
if (var15 != null) {
try {
fileInputStream.close();
} catch (Throwable var11) {
var15.addSuppressed(var11);
}
} else {
fileInputStream.close();
}
}
}
} catch (Exception var14) {
String message = var14.getMessage();
System.out.println(message);
}
}
}
文件专属流:
java.io.FileInputStream
java.io.FileOutputStream
案例:实现文件复制
public static void show() throws IOException {
//当文件不存在时,会报错
InputStream fis = new FileInputStream("D:\\ceshi\\ceshi.txt");//选择被复制的文件
//当文件不存在时,会自己创建一个文件。
FileOutputStream fos = new FileOutputStream("D:\\ceshi.txt",true);//指定数据的输出路径
//一次读取多个字节,最多读取“数组.length”个字节
byte[] b= new byte[1024];
int len;
//read(),这个方法的返回值是:读取到的字节数量。(不是字节本身);1个字节都没有读取到返回-1(文件读到末尾)
while ((len = fis.read(b))!=-1){
// 读取多个个字节,就存多少个字节。
fos.write(b,0,len);
}
//流必须关闭,节约资源
fis.close();
fos.close();
}
java.io.FileReader
java.io.FileWriter
案例:实现文件复制
public static void show() throws IOException {
//当文件不存在时,会报错
FileReader fR= new FileReader("D:\\ceshi\\ceshi.txt");//选择被复制的文件
//当文件不存在时,会自己创建一个文件。
FileWriter fW = new FileWriter("D:\\ceshi.txt",true);//指定数据的输出路径
// 定义字符数组,作为装字符数据的容器
char[] b= new char[1024];
// 定义变量,保存有效字符个数
int len;
//read(),这个方法的返回值是:读取到的字符数量。;1个字符都没有读取到返回-1(文件读到末尾)
while ((len = fR.read(b))!=-1){
// 读取多个个字节,就存多少个字节。
fW.write(b,0,len);
}
//流必须关闭,节约资源
fR.close();
fW.close();
}
缓冲流专属:
缓冲流是对4个基本的FileXxx
流的增强,所以也是4个流
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
public static void main(String[] args) throws NoSuchMethodException, IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("D:/ceshi.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:/ceshi2.txt"));
int len;
while ((len=bufferedReader.read())!=-1){
bufferedWriter.write(len);
}
bufferedReader.close();
bufferedWriter.close();
}
带Buffered的流和自己写的数组缓冲对比
自己写 的数组的读写和带Buffered的读取哪个更快?
自己写数组会略胜一筹,因为读和写操作的是同一个数组
而Buffered操作的是两个数组
代码演示:
public class demo12 {
public static void main(String[] args) throws NoSuchMethodException, IOException {
//这是测试Buffered流的速度
long l = System.currentTimeMillis();
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:/ceshi.mp4"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("D:/ceshi2.mp4"));
int len;
while ((len=bufferedInputStream.read())!=-1){
bufferedOutputStream.write(len);
}
bufferedInputStream.close();
bufferedOutputStream.close();
long l1 = System.currentTimeMillis();
long l2 = l1 - l;
System.out.println("使用Buffered流需要的时间:"+l2);
//使用FIle流的速度
FileInputStream fileInputStream = new FileInputStream("D:/ceshi.mp4");
FileOutputStream fileOutputStream = new FileOutputStream("D:/ceshi2.mp4");
byte[] arr = new byte[1024*8];
int len1;
while ((len1=fileInputStream.read(arr))!=-1){
fileOutputStream.write(arr);
}
fileInputStream.close();
fileOutputStream.close();
long l3 = System.currentTimeMillis();
long l4 = l3 - l1;
System.out.println("使用File流需要的时间:"+l4);
}
}
输出:
使用Buffered流需要的时间:297
使用File流需要的时间:31