1、I是指Input(输入),O是指Output(输出)。
2、在Java中,文件的输入和输出是通过流(Stream)来实现的,流的概念源于Unix中管道(pipe)的概念。在Unix系统中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等
3、一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。对于流而言,我们不用关心数据是如何传输的,只需要向源端输入数据,向目的端获取数据即可
4、流按照处理数据的单位,可以分为字节流和字符流;按照流向分为输入流和输出流(注意:输入流和输出流都是站在程序的角度参照的)
字节流用于处理以字节为单位的二进制文件(如音乐、图片等):
//例:
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream=null;//创建输入流变量
FileOutputStream fileOutputStream=null;//创建输出流变量
try {
fileInputStream = new FileInputStream("D:\\图片\\1.jpg");//输入流实例赋值
fileOutputStream = new FileOutputStream("D:\\图片\\2.jpg");//输出流实例赋值
int date = 0;
while((date=fileInputStream.read())!=-1) {//读取文件并暂存入date中,当到文件结尾,没有字节时返回-1
fileOutputStream.write(date);//写文件,将读取到的文件写入输出实例中
}
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();
}
}
}
}
}
以上程序运行过后,将在D:\图片目录下生成2.jpg文件,内容与1.jpg一样
但是这样一个字节一个字节读写,将会很低效,那么我们能不能一次进行多个字节的输入输出呢?答案是:可以的
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream=null;//创建输入流变量
FileOutputStream fileOutputStream=null;//创建输出流变量
try {
fileInputStream = new FileInputStream("D:\\图片\\1.jpg");
fileOutputStream = new FileOutputStream("D:\\图片\\2.jpg");
byte[] date=new byte[1024];//定义一个byte数组,指定能存入1024个数
int length = 0;
while((length=fileInputStream.read(date))!=-1) {//读取文件并暂存入date中并返回date个数赋值给length,当到文件结尾,没有字节时返回-1
fileOutputStream.write(date,0,length);//写文件,将读取到的文件写入输出实例中,从date中的第一个数,输出到第1024个
}
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();
}
}
}
}
}
上述代码一次执行1024个字节,明显要比第一种高效很多
字符流与字节流执行过程类似,但是字节符流用于处理字节文件(文本文件):
//例
public class Test {
public static void main(String[] args) {
FileReader filereader=null;//创建字符流输入流变量
FileWriter filewriter=null;//创建字节流输出流变量
try {
filereader = new FileReader("D:\\Program_Files\\博客.txt");//输入流实例赋值
filewriter = new FileWriter("D:\\Program_Files\\222.txt");//输出流实例赋值
int date=0;
while((date=filereader.read())!=-1) {//读取文件并暂存入date中,当到文件结尾,没有字节时返回-1
filewriter.write(date);//写文件,将读取到的文件写入输出实例中
}
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();
}
}
}
}
}
以上代码是将一个文本文档传到另一个地方(222.txt)
但是,同样的问题,低效。解决办法,也是相当雷同。如下:
public class Test {
public static void main(String[] args) {
FileReader filereader=null;
FileWriter filewriter=null;
try {
filereader = new FileReader("D:\\Program_Files\\博客.txt");
filewriter = new FileWriter("D:\\Program_Files\\222.txt");
int length=0;
char[] date=new char[1024];//指定数组大小,即一次传输的量
while((length=filereader.read(date))!=-1) {
filewriter.write(date,0,length);;
}
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();
}
}
}
}
}
上面说到的I/O流都是直接访问硬盘,进行文件的读写操作,虽然我们通过改变一次传输的量的方式,使效率提高,但仍不足够
缓冲流是一种装饰器类,目的是让原字节流、字符流新增缓冲的功能以提高读取或写入。简单的说,通过缓存存取,间接输入输出
用于字节流:
缓冲字节输入流:
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[] date =new byte[1024];
while((length=bufferedInputStream.read(date))!=-1) {
bufferedOutputStream.write(date,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) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try {
FileReader filereader=null;
FileWriter filewriter=null;
BufferedReader bufferedReader=null;
BufferedWriter bufferedWriter=null;
try {
filereader = new FileReader("D:\\Program_Files\\1.txt");
filewriter = new FileWriter("D:\\Program_Files\\222.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();
}
}
}
}
}
由于文件自身编码方式和程序运行时使用的默认编码方式不一致,致使程序读取或输出字符文件时可能会出现乱码,这时可以使用字节流操作文件,然后再将字节流转换成字符流,这一转换过程可以借助转换流实现
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:\\qwe.conj"));//实例化数据流
dateoutputstream.writeDouble(a);//输出数据
dateoutputstream.flush();
} catch (Exception e) {
e.printStackTrace();
}
try {
DataInputStream dataInputStream=new DataInputStream(new FileInputStream("D:\\qwe.conj"));//实例化数据流
double q=dataInputStream.readDouble();//读入数据
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是,需要注意的是,数据流可以输出不同的基本数据类型的数据和字符串类型的数据,但是在读取的时候,需要分别用相应的类型的方法和正确的顺序进行读取。