Java的IO流都是由四个抽象基类派生的:
- InputStream、OutputStream:字节流,传输二进制文件,比如音频、视频、图片等。
- Reader、Writer:字符流,传输文本文件。
在计算机中,所有的文件都能以二进制(字节)形式存在,Java的IO中针对字节传输操作提供了一系列的流,统称为字节流。字节流有两个抽象基类InputStream和OutputStream,分别处理字节流的输入输出,所有的字节输入流都继承自InputStream类,所有的字节输出流都继承自OuyputStream类。
在Java中,提供了一系列用于操作文件读写的有关方法,接下来先了解一下InputStream类的方法:
- int available():返回此输入流下一个方法调用可以不受阻塞的从此输入流读取的估计字节流。
- void close():关闭此输入流并释放与该流关联的所有系统资源。
- void mark(int readlimit):在此输入流中标记当前的位置。
- boolean markSupported():测试粗输入流是否支持mark和reset方法。
- long skip(long n):跳过和丢弃此输入流中数据的n个字节。
- int read():从输入流中读取数据的下一个字节。
- int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中,返回读取的字节流。
- int read(byte[] b,int off,int len):将输入流中最多len个数据字节读入byte数组。
- void reset():将此流重新定位到最后一次对此输入流调用mark方法时的位置。
下面我再来介绍一下OutputStream类的相关方法:
- void close():关闭此输出流并释放与此流有关的所有系统资源。
- void flush():刷新此输出流并强制写出所有缓冲的输出字节。
- void write(byte[] b):将b.length个字节从指定的byte数组写入此输出流。
- void write(int b):将指定的字节写入此输入流。
- void write(byte[] b,int off,int len):将指定byte数组中从偏移量off开始的len个字节写入此输出流。
字节流读写文件
首先在当前目录新建一个文本文件read.txt,文件内容为Hello World!!!
创建文件完成后,开始编写代码:
import java.io.FileInputStream;
public class TestFileInputStream {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileInputStream fis=null;
try {
//创建文件输入流对象
fis=new FileInputStream("read.txt");
int n=512; //设定读取的字节数
byte buffer[]=new byte[n];
//读取输入流
while((fis.read(buffer,0,n)!=-1)&&(n>0)){
System.out.print(new String(buffer));
}
}catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}finally {
try {
fis.close();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
运行结果:
与FileInputStream对应的是FileOutputStream,它是用来将数据写入文件,操作文件字节输出流的,接下来通过一个案例来演示如何将数据写入文件。
import java.io.*;
public class TestFileOutputStream {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("输入要保存文件的内容:");
int count,n=512;
byte buffer[]=new byte[n];
count=System.in.read(buffer); //读取标准输入流
//创建文件输出流对象
FileOutputStream fos=new FileOutputStream("read.txt");
fos.write(buffer,0,count); //写入输出流
System.out.println("已保存到read.txt文件!");
fos.close(); //释放资源
}
}
运行结果:
在实际开发中,往往读和写都是结合使用的,比如文件的复制。
接下来通过一个案例来演示输入输出流实现文件的复制。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileCopy {
public static void main(String[] args) throws IOException{
//创建文件输入流对象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//创建文件输出流对象
FileOutputStream fos=new FileOutputStream("tar\\lina_new.jpg");
int len; //定义len,记录每次读取的字节数
//复制文件前的系统时间
long begin=System.currentTimeMillis();
//读取文件并判断是否到达文件末尾
while((len=fis.read())!=-1) {
fos.write(len); //将独到的字节写入文件
}
long end=System.currentTimeMillis();
System.out.println("复制文件耗时:"+(end-begin)+"毫秒");
fis.close();
fos.close();
}
}
运行结果:
字节流的缓冲区
上面的方法复制文件,频繁操作文件,效率非常低,利用字节流的缓冲区可以解决这一问题,提高效率。
接下来通过一个案例来演示如何在复制文件时应用缓冲区提高效率。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileCopyBuffer {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//创建文件输入流对象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//创建文件输出流对象
FileOutputStream fos=new FileOutputStream("tar\\lina_new1.jpg");
byte[] b=new byte[512]; //定义缓冲区大小
int len; //定义len,记录每次读取的字节数
//复制文件前的系统时间
long begin=System.currentTimeMillis();
//读取文件并判断是否到达文件末尾
while((len=fis.read(b))!=-1) {
fos.write(b,0,len); //将独到的字节写入文件
}
long end=System.currentTimeMillis();
System.out.println("复制文件耗时:"+(end-begin)+"毫秒");
fis.close();
fos.close();
}
}
运行结果:
字节缓冲流
在IO中的一些流会用到装饰设计模式,分别是BufferedInputStream类和BUfferedOutputStream类,他们的构造方法中分别接收InputStream和OutputStream类型的参数作为被修饰的对象,在执行读写操作时提供缓冲功能。
接下来通过一个案例来演示这两个流的使用。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestBuffered {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//创建文件输入流对象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//创建文件输出流对象
FileOutputStream fos=new FileOutputStream("tar\\lina_new2.jpg");
//将创建的节点流的对象作为形参传递给缓冲流的构造方法中
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedOutputStream bos=new BufferedOutputStream(fos);
int len; //定义len,记录每次读取的字节数
//复制文件前的系统时间
long begin=System.currentTimeMillis();
//读取文件并判断是否到达文件末尾
while((len=bis.read())!=-1) {
bos.write(len); //将独到的字节写入文件
}
long end=System.currentTimeMillis();
System.out.println("复制文件耗时:"+(end-begin)+"毫秒");
bos.close();
bis.close();
}
}
运行结果: