IO流
I是指Input(输入),O是指Output(输出)
在Java中,文件的输入和输出都是通过流(Stream)来实现的,流的概念源于Unix中pipe(管道)的概念。在Unix系统中,管道是一条不间断的字节流,用来实现程序或者进程间的通信,或读写外围设备、外部文件等。
一个流,必须有源端和目的端,他们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。对于流而言,我们不用关心数据是如何传输的,只需要向源端输入数据,向目的端获取数据即可。
流按照处理数据的单位,可以分为字节流和字符流;按照流向分为输入流和输出流(输入流和输出流都是站在程序的角度思考的)
字节流
字节流用于处理以字节为单位的二进制文件(如音乐、图片等);
InputStream抽象类是所有输入字节流类的直接或间接父类,FileInputStream是其重要的子类
OutputStream抽象类是所有输出字节流类的直接或间接父类,FileOutputStream是其重要的子类
FileInputStream
常用构造方法:
- FileInputStream(File file); 通过file对象创建FileInputStream对象
- FileInputStream(String name); 通过文件(非目录)路径来创建FileInputStream对象。
常用方法:
- int read();从输入流中读取单个字节的数据;如果已经达到文件末尾,则返回-1。
- int read(byte[] b);从输入流中将最多b.length个字节的数据读入一个byte数组中,以整数形式返回存入数组中的实际字节个数;如果已经达到文件末尾则返回-1
- void close():关闭此文件输入流并释放与此流有关的所有系统资源
FileOutputStream
常用构造方法:
- FileOutputStream(File file);通过File对象创建FileOutputStream对象
- FileOutputStream(String name);通过文件路径来创建FileOutputStream对象。
常用方法:
- void write(int b);将指定的单个字节数据写入此文件输出流。
- void write(byte[] b, int off, int len);将byte数组中从off开始的len个字节写入此文件输出流
- void flush();刷新字节输出流,并强制写出缓冲内所有字节数据
- void close();关闭此文件输出流,并释放所有与此流有关的系统资源
我们将FileOutputStream与FileInputStream综合起来叙述这两个类的各种方法。
传输示意图:
- 每次传输单个字节:
public class Test{
public static void main(String[] args){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try{
fileInputStream = new FileInputStream("D:\\hello.jpg");//相当于java与输入字节流接通了一根管道
fileOutputStream = new FileOutputStream("D:\\world.jpg");//相当于java与输出字节流接通了一根管道
int data = 0;
while((data=fileInputStream.read())!=-1){//每次读取一个字节的数据,把读出来的数据存到data中,直到没数据data为-1
fileOutputStream.write(data);//将data写入目标文件路径
}
fileOutputStream.flush();//强制写出缓冲内所有字节数据,防止数据停留在缓冲中
} catch (Exception e) {
e.printStackTrace();
}finally{//释放资源
if(fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 每次传入多个字节
public class Test{
public static void main(String[] args){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try{
fileInputStream = new FileInputStream("D:\\hello.jpg");//相当于java与输入字节流接通了一根管道
fileOutputStream = new FileOutputStream("D:\\world.jpg");//相当于java与输出字节流接通了一根管道
byte[] car = new byte[1024];//定义一个缓冲数组car,类似与运货的车,一下可以装1024个货
int length= 0;
while((length=fileInputStream.read(car))!=-1){//每次读取length个字节,最多读取1024个字节的数据,把读出来的数据存到data中,直到没数据data为-1
fileOutputStream.write(car,0,length);//从car数组的第0位开始,将length长度的car写入目标文件路径
}
fileOutputStream.flush();//强制写出缓冲内所有字节数据,防止数据停留在缓冲中
} catch (Exception e) {
e.printStackTrace();
}finally{//释放资源
if(fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流
Java虚拟机将字节转化为了两个字节的Unicode字符就形成了字符流,字符流用于处理以Unicode字符为单位的文本文件(如记事本文件)
Reader抽象类是所有输入字符流类的直接或者间接父类,FileReader是其重要子类
Writer抽象类是所有输出字符流类的直接或者间接父类,FileWriter是其重要子类
FileReader
常用构造方法
- FileReader(File file);通过File对象创建FileReader对象
- FileReader(String fileName);通过文件路径来创建FileReader对象。
常用方法
- int read();从输入流中读取单个字符的数据;如果已经达到文件末尾,则返回-1。
- int read(char[] c);从输入流中将最多c.length个字符的数据读入一个char数组中,以整数形式返回存入数组中的实际字符个数;如果已经达到文件末尾则返回-1
- void close():关闭此文件输入流并释放与此流有关的所有系统资源
FileWriter
常用构造方法
- FileWriter(File file);通过File对象创建FileWriter对象
- FileWriter(String fileName);通过文件路径来创建FileWriter对象。
常用方法
- void write(int c);将指定的单个字符数据写入此文件输出流。
- void write(char[] c, int off, int len);将char数组中从off开始的len个字符写入此文件输出流
- void flush();刷新字符输出流,并强制写出缓冲内所有字符数据
- void close():关闭此文件输出流并释放与此流有关的所有系统资源
我们将FileReader与FileWriter综合起来叙述这两个类的各种方法。
- 每次传输单个字符:
public class Test{
public static void main(String[] args){
FileReader fileReader= null;
FileWriter fileWriter= null;
try{
fileReader= new FileReader ("D:\\hi.txt");//相当于java与输入字符流接通了一根管道
fileWriter= new FileWriter ("D:\\hey.txt");//相当于java与输出字符流接通了一根管道
int data = 0;
while((data=fileReader.read())!=-1){//每次读取一个字符的数据,把读出来的数据存到data中,直到没数据data为-1
fileWriter.write(data);//将data写入目标文件路径
}
fileWriter.flush();//强制写出缓冲内所有字符数据,防止数据停留在缓冲中
} catch (Exception e) {
e.printStackTrace();
}finally{//释放资源
if(fileReader!=null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileWriter!=null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 每次传输多个字符
public class Test{
public static void main(String[] args){
FileReader fileReader= null;
FileWriter fileWriter= null;
try{
fileReader= new FileReader ("D:\\hi.txt");//相当于java与输入字符流接通了一根管道
fileWriter= new FileWriter ("D:\\hey.txt");//相当于java与输出字符流接通了一根管道
char[] car = new char[1024];//定义一个缓冲数组car,类似与运货的车,一下可以装1024个货
int length = 0;
while((length = fileReader.read(car))!=-1){//每次读取length个字符的数据,直到没数据length为-1
fileWriter.write(car,0,length);//从0开始将length长度的car写入目标文件路径
}
fileWriter.flush();//强制写出缓冲内所有字符数据,防止数据停留在缓冲中
} catch (Exception e) {
e.printStackTrace();
}finally{//释放资源
if(fileReader!=null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileWriter!=null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲流
上面说到的IO流都是直接访问硬盘,进行文件的读写操作,虽然我们通过改变一次传输的量的方式,使效率提高,但我们可以使效率更高一些
缓冲流是一种装饰器类,目的是让原字节流、字符流新增缓冲的功能以提高读取或写入。简单的说,通过缓存存取,间接输入输出
示意图:
用于字节流:
缓冲流是一种装饰器,目的是让原字节流、字符流新增缓冲的功能以提高读取或写入。
缓冲字节输入流:BufferedInputStream(InputStream in)
缓冲字节输出流:BufferedOutputStream(OutputStream out)
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try {
fileInputStream = new FileInputStream("D:\\1.jpg");
fileOutputStream = new FileOutputStream("D:\\2.jpg");
bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
int length = 0;
byte[] car =new byte[1024];
while((length=bufferedInputStream.read(car))!=-1) {
bufferedOutputStream.write(car,0,length);
}
bufferedOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedInputStream!=null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedOutputStream!=null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲字符输入流:BufferedReader(Reader in)
缓冲字符输出流:BufferedWriter(Writer out)
public class Test {
public static void main(String[] args) {
FileReader filereader=null;
FileWriter filewriter=null;
BufferedReader bufferedReader=null;
BufferedWriter bufferedWriter=null;
try {
filereader = new FileReader("D:\\1.txt");
filewriter = new FileWriter("D:\\2.txt");
bufferedReader=new BufferedReader(filereader);
bufferedWriter=new BufferedWriter(filewriter);
int length=0;
char[] car=new char[1024];
while((length=bufferedReader.read(car))!=-1) {
bufferedWriter.write(car,0,length);;
}
bufferedWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(filereader!=null) {
try {
filereader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(filewriter!=null) {
try {
filewriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedWriter!=null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedReader!=null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
转换流
由于文件自身编码方式和程序运行时使用的默认编码方式不一致,致使程序读取或输出字符文件时可能会出现乱码,这时可以使用字节流操作文件,然后再将字节流转换成字符流,这一转换过程可以借助转换流实现
InputStreamReader();(字节输入流→字符输入流)
- InputStreamReader(InputStream in);
- InputStreamReader(InputStream in,String charsetName);
OutputStreamWriter();(字节输出流→字符输入流)
- OutputStreamWriter(InputStream in);
- OutputStreamWriter(InputStream in,String charsetName);
public class Test {
public static void main(String[] args) {
InputStreamReader inputStreamReader=null;//定义转换流变量
OutputStreamWriter outputStreamWriter=null;
FileInputStream fileInputStream=null;//定义字节流变量
FileOutputStream fileOutputStream=null;
try {
fileInputStream=new FileInputStream("D:\\Program_Files\\1.txt");//字节流实例化
fileOutputStream=new FileOutputStream("D:\\Program_Files\\2.txt");
inputStreamReader = new InputStreamReader(fileInputStream);//转换流实例化
outputStreamWriter = new OutputStreamWriter(fileOutputStream);
int length=0;
char[] car=new char[1024];
while((length=inputStreamReader.read(car))!=-1) {
outputStreamWriter.write(car,0,length);;
}
outputStreamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {//释放资源
if(fileInputStream!=null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStreamReader!=null) {
try {
inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStreamWriter!=null) {
try {
outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
数据流
通过DataInputStream和DataOutputStream数据流可以直接操作基本数据类型和字符串
public class Test {
public static void main(String[] args) {
try {
double a=9.9;
DataOutputStream dateoutputstream= new DataOutputStream(new FileOutputStream("D:\\1.temp"));
dateoutputstream.writeDouble(a);
dateoutputstream.flush();
} catch (Exception e) {
e.printStackTrace();
}
try {
DataInputStream dataInputStream=new DataInputStream(new FileInputStream("D:\\1.conj"));//实例化数据流
double q=dataInputStream.readDouble();
} catch (Exception e) {
e.printStackTrace();
}
}
}