Java中详述IO流

什么是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对象。
FileOutputStream常用构造方法:
FileOutputStream(File file) :通过File对象创建FileOutputStream对象。
FileOutputStream(String name) :通过文件(非“目录”)路径创建FileOutputStream对象。
FileOutputStream(File file, boolean append):通过File对象创建FileOutputStream对象;第二个参数如果为true ,则字节将被写入文件的末尾而不是开头。
首先要讲一下:输入流中的.read()方法:
.read()可以将输入流中的内容遍历传值,直至遍历完全,返回值为-1,因此通常以**.read()!=-1**作为判定文件中的数据是否遍历输出完全的标志。
字节输出流的方式有两种:按字节一个一个输出或者是自定义一个数组作为载具(可以承载一定数量的数据),通过载具进行输出。下面给出代码实例来进行讲述:
按字节逐个输出:

FileInputStream inputStream = new FileInputStream("D:\\nicecloud.mp4");//创建输入流对象,将D盘的nicecloud.mp4文件输入只inputStream中
        FileOutputStream outputStream = new FileOutputStream("G:\\a.mp4",true);//创建输出流对象,程序运行时在G盘创建一个名为a.mp4的空文件,用于之后数据输出过来的容器
        int data;
        while ((data = inputStream.read())!=-1){
            outputStream.write(data);//对数据逐个进行输出
        }

在执行程序时,我们会发现以这种字节逐个数出的程序耗时极大,因此我们引入一个数组作为载具承载一定数量的数据进行输出:
借助载具输出:

        FileInputStream inputStream = new FileInputStream("D:\\nicecloud.mp4");
        FileOutputStream outputStream = new FileOutputStream("G:\\a.mp4",true);
        int length;
        byte [] car = new byte[1024];//创建容器car,字节流使用byte类型数组
        while ((length = inputStream.read(car))!=-1){//将car中的数据长度值传至length变量中。
            outputStream.write(car, 0, length);//将car中的数据从0到length全部输出到文件中
        }
        outputStream.flush();//刷新字节输出流并强制写出缓冲内所有字节数据,写出的数据全部写出在目标输出文件中
        outputStream.close();//释放资源outputStream对象
        inputStream.close();//释放资源inputStream对象

在运行这个程序的时候,我们就会发现程序执行的非常迅速,能够更快的完成数据输入输出的要求。
注意:
FileOutputStream(File file) 、 FileOutputStream(String name) 或FileOutputStream(File file, false)创建FileOutputStream对象时会创建一个新的空文件;如果使用FileOutputStream(File file, true)创建FileOutputStream对象,则只在第一次执行时创建一个新的空文件。

字符流

Java虚拟机将字节转化为2个字节的Unicode字符就形成了字符流,字符流用于处理以Unicode字符为单位的文本文件(如记事本文件等)。
Reader抽象类是所有输入字符流类的直接或间接父类, FileReader是其重要子类;Writer抽象类是所有输出字符流类的直接或间接父类,FileWriter是其重要子类。
FileReader常用构造方法:
FileReader(File file) :通过File对象创建FileReader对象。
FileReader(String fileName) :通过文件(非“目录”)路径创建FileReader对象。
FileWriter常用构造方法:
FileWriter(File file) :通过File对象创建FileWriter对象。
FileWriter(String fileName) :通过文件(非“目录”)路径创建FileWriter对象。
FileWriter(File file, boolean append):通过File对象创建FileWriter对象;第二个参数如果为true ,则字节将被写入文件的末尾而不是开头。
下面我们模仿字节流代码进行代码展示:
逐个输出:

        FileReader reader = new FileReader("C:\\1.txt");
        FileWriter writer = new FileWriter("G:\\copy.txt",true);
        int data;
        while ((data = reader.read())!=-1){
            writer.write(data);
        }

此时我们可以看观察结果:
在这里插入图片描述
并没有想象当中将1.txt中的字符输出到copy.txt文件当中,这是因为1.txt中的内容太少且没有进行flush()的清空缓存的操作,这些字符都位于缓存中没有实现输出,因此我们需要加上.flush()方法,然后再观察结果:

FileReader reader = new FileReader("C:\\1.txt");
        FileWriter writer = new FileWriter("G:\\copy.txt",true);
        int data;
        while ((data = reader.read())!=-1){
            writer.write(data);
        }
        writer.flush();
        writer.close();
        reader.close();

结果显示为预期结果:
在这里插入图片描述
借助载具输出:

        FileReader reader = new FileReader("C:\\1.txt");
        FileWriter writer = new FileWriter("G:\\copy.txt",true);
        char [] car = new char[1024];//创建容器car,字符流使用char类型数组
        int length;
        while ((length = reader.read(car))!=-1){
            writer.write(car,0, length);
        }
        writer.flush();
        writer.close();
        reader.close();

缓冲流

在上述运行程序的过程中,是从硬盘上直接进行文件的输入和输出的操作,而在硬盘上进行读取和改写的操作不如在缓冲区进行迅速,因此在文件较大时,使用缓冲流能够更好地实现数据的输入与输出。
缓冲流是一种装饰器类,目的是让原字节流、字符流新增缓冲的功能以提高读取或写入。
缓冲字节输入流:BufferedInputStream(InputStream in):
缓冲字节输出流:BufferedOutputStream(OutputStream out):
下面我们根据字节流和字符流的借助载具批量输入输出的代码为例:
字节型:
BufferedInputStream中需要使用InputStream类的对象,而FileInputStream类是InputStream类的子类,因此,所使用的FileInputStream类的对象一个上转型对象,BufferedOutputStream 同理。

        FileInputStream inputStream = new FileInputStream("D:\\nicecloud.mp4");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);//BufferedInputStream中需要使用InputStream类的对象,而FileInputStream类是InputStream类的子类,因此,此处的inputStream是一个上转型对象。
        FileOutputStream outputStream = new FileOutputStream("G:\\a.mp4",true);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
        byte [] car = new byte[1024];
        int length;
        while ((length = bufferedInputStream.read(car))!=-1){
            bufferedOutputStream.write(car,0,length);
        }
        bufferedOutputStream.flush();
        bufferedOutputStream.close();
        bufferedInputStream.close();

字符流:
BufferedReader中需要使用Reader类的对象,而FileReader类是Reader类的子类,因此,所使用的FileReader类的对象一个上转型对象,BufferedWriter 同理。

        FileReader reader= new FileReader("C:\\1.txt");
        BufferedReader bufferedReader = new BufferedReader(reader);//BufferedReader中需要使用Reader类的对象,而FileReader类是Reader类的子类,因此,此处的reader是一个上转型对象。
        FileWriter writer = new FileWriter("G:\\copy.txt");
        BufferedWriter bufferedWriter = new BufferedWriter(writer);
        char [] car = new char[1024];
        int length;
        while ((length = bufferedReader.read(car))!=-1){
            bufferedWriter.write(car,0,length);
        }
        bufferedWriter.flush();
        bufferedWriter.close();
        bufferedReader.close();

转换流

为什么要是用转换流:
由于文件自身编码方式和程序运行时使用的默认编码方式不一致,致使程序读取或输出字符文件时可能会出现乱码,这时可以使用字节流操作文件,然后再将字节流转换成字符流,这一转换过程可以借助转换流实现。
InputStreamReader(字节输入流---->字符输入流):
InputStreamReader(InputStream in) :
InputStreamReader(InputStream in, String charsetName):
OutputStreamWriter(字节输出流---->字符输出流):
OutputStreamWriter(OutputStream out) :
OutputStreamWriter(OutputStream out, String charsetName) :
下面给出代码展示:

        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\1.txt"));
        InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream,"GBK");
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("G:\\copy.txt"));
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(bufferedOutputStream,"GBK");//中文编码格式为GBK
        char [] car = new char[1024];
        int length;
        while ((length = inputStreamReader.read(car))!=-1){
            outputStreamWriter.write(car,0,length);
        }
        outputStreamWriter.flush();
        outputStreamWriter.close();
        inputStreamReader.close();

结果为:
在这里插入图片描述
此时我们可以查看文件的类型:
1.txt采用的是ANSI方式进行编码:
在这里插入图片描述
copy.txt采用的是UTF-8方式进行编码:
在这里插入图片描述
采用字符流中的方式进行编码我们会发现结果显示为乱码:
在这里插入图片描述
因此我们通常使用转换流来解决输入流和输出流的文件编码格式不统一的情况。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值