【Java IO流 + 案例分析】

IO流

什么是IO流

IO,即inout,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。流(stream),是一个抽象的概念,是一连串的数据(字符或字节),以先进先出的方式发送信息的通道。

在我们电脑中所有的文件,文档,音频,视频,图片都可以进行读和写,他们都经过流的形式进行

一般来说关于流的特性有下面几点:

1.先进先出:最先写入输出流的数据最先被输入流读取到。
2.顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
3.只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

什么是缓冲流

缓冲流是程序跟磁盘交互时非常重要的部分,我们知道,程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。

缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。

IO流的分类

IO流分为:输入流,输出流

输入流的意思就是:从磁盘中读取数据到内存(java代码)

输出流的意思就是:从内存(java代码)写入数据到磁盘中某个文件

输入流分为:字节输入流,字符输入流

输出流分为:字节输出流,字符输出流

在这里插入图片描述

字节流和字符流的其他区别:

字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。

字节输入流(FileInputStream)

案例:磁盘上面有一个1.txt文件,现在要将1.txt文件中的内容读取到内存(Java代码中)

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //1.创建File对象,是咱们本地磁盘文件的一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.创建文件字节输入流对象,来操作1.txt
        //将c:/aaa/1.txt文件转为字节输入流的形式,之后可以按照流的形式读取到内存中
        FileInputStream fis = new FileInputStream(file);
       //3.加上缓冲功能
        BufferedInputStream bis = new BufferedInputStream(fis);
        //5.创建一个缓冲区的数组  byte  是byte类型的数组
        byte[] buf = new byte[1024 * 4];//缓冲区4096字节
        //现在数组是空的
        //6.读取数据
        // 如果没有字节可用,因为流在文件末尾,则返回值-1
        int length = -1;
        //如果length=-1  那么就会到达流的末尾  就证明后面没哟数据
        //循环结束,不要再读了
        while ((length = bis.read(buf)) != -1) {
            System.out.println(new String(buf, 0, length));
        }
        //7.流是需要关闭的
        bis.close();
        fis.close();
    }
}
字节输出流(FileOutputStream)

案例:Java代码中有一个字符串 将这个字符串写入磁盘某一个文件中

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //将Java代码中的一个字符串写入到咱们的磁盘的某一个文件中
        //1.创建File对象,文件路径对象  告知编译器要把数据写到哪个文件中
        File file = new File("c:/aaa/2.txt");
        //2.实例化字节输出流对象
        FileOutputStream fos = new FileOutputStream(file);
        //3.对FileOutputStream  加上缓冲的效果
        //猜测一下  FileInputStream所对应的缓冲流  BufferedInputStream
        //FileOutputStream  所对应的缓冲流  BufferedOutputStream
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //4.将一个字符串写入到磁盘中
        String str = "大家再等我一天,后天见面!!!";
        //	write(byte[] b)
        //咱们的参数是字节数组,咋办?str是一个字符串 但是参数是一个字节数组,咋解决?
        //str是字符串 不能强转  将字符串转为字节数组,没有讲过!!!
        //将str字符串转为字节数组
        byte[] bytes = str.getBytes();
        bos.write(bytes);
        //5.写完以后一定要刷新流然后关闭流
        bos.flush();//没有实际的意义,可以不写的
        //6.关闭流
        //在输入流的时候一定是先开的后关,后开的先关
        bos.close();
        fos.close();
    }
}

案例:对比有缓冲流,和没有缓冲流的效率对比

public class Demo1 {
    public static void main(String[] args) throws IOException {
        copyVideo1();
    }
    //现在咱们讲的这个是带有缓冲的,看看带有缓冲视频的复制的耗时多少 2610ms
    //写一个方法将bbb文件夹下面的3.map4格式的视频复制到aaa文件夹下面
    //用带缓冲的,效率高
    public static void copyVideo () throws IOException {
        //获取系统的当前的毫秒数
        long start = System.currentTimeMillis();
        //1.创建字节缓冲输入流  将磁盘的数据读取到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("c:/bbb/3.mp4")));
        //2.创建字节缓冲输出流   从内存写入到的文件  源文件是mp4格式,写入到的也必须是mp4格式的
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("c:/aaa/goudan.mp4")));
        //3.准备一个字节数组 缓冲区数组
        byte[] buf = new byte[4 * 1024];//代码走到这一步是空的
        //4.从磁盘读取数据到内存
        int length = -1;
        //这个视频很大,依靠循环来读取,每次读4 * 1024字节
        while ((length = bis.read(buf)) != -1) {//从磁盘上读取数据到buf缓冲数组中
            //每次循环 buf数组中有值,顺便依靠循环写入到磁盘
            System.out.println("qwer");
            bos.write(buf, 0, length);
        }
        //5.关闭流
        bos.close();
        bis.close();
        //复制完以后再得到一个毫秒数,相减 就得到复制一个视频需要的时间
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
    //看一下不带缓冲的流的读写
    public static void copyVideo1 () throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream(new File("c:/bbb/3.mp4"));
        FileOutputStream fos = new FileOutputStream(new File("c:/aaa/goudan.mp4"));
        int length = -1;
        while ((length = fis.read()) != -1) {
            fos.write(length);
        }
        fos.close();
        fis.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

字符输入流(FileReader)

FileReader:

是一个阅读字符文件的便利类,是专门处理字符文件的,比如txt文件。

音频视频图片不能使用这个流。

案例:将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中
        //和字节流一模一样
        //1.新建一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.新建FileReader  对象 字符输入流
        FileReader fr = new FileReader(file);
        //3.FileRFeader没有缓冲的效果,可以加上缓冲的效果
        //杂加?BufferedReader
        BufferedReader br = new BufferedReader(fr);
        //4.字节的缓冲数组 是字节
        //字符的缓冲数组  是字符
        char[] cbuf = new char[4];//缓冲区是4个字符
        //这个方法是用的!!!
        //int read()一次读取,一个字符
        //5.read(char[] cbuf) 将文件内容读取到字符数组中(缓冲区)
        int length = -1;
        while ((length = br.read(cbuf)) != -1) {
            System.out.println(length);
            //6.将数组展示到控制台
            System.out.println(new String(cbuf, 0, length));
        }
        //7.关闭流
        br.close();
        fr.close();
    }
}
字符输出流(FileWriter)

案例:将一个字符串类型的数据写入到磁盘中

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //从内存写入数据到磁盘的文件中
        File file = new File("c:/aaa/2.txt");
        FileWriter fw = new FileWriter(file);
        //加缓冲流
        BufferedWriter bw = new BufferedWriter(fw);
        //viod writer(char[] cbuf, int off, int length);
        String str = "今天的天气真的太热了";
        //将字符串转为char数组
        char[] chars = str.toCharArray();
        //将chars数组中  从0 开始  取3个字符写入到缓冲流中
        bw.write(chars, 3, 3);
        bw.close();
        fw.close();
    }
}

拷贝文件案例

案例:复制一本小说到另一个盘符下

public class Demo4 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File("c:/bbb/DiBa.txt")));
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("c:/aaa/sb1.txt")));

        int length = -1;
        char[] cbuf = new char[4 * 1024];
        while ((length = br.read(cbuf)) != -1) {
            bw.write(cbuf, 0, length);
        }
        bw.close();
        br.close();
    }
}

在进行拷贝文件时,我们会写许多的重复代码,那我们能想到什么呢?

对!我们可以对其进行封装,所以我们创建一个FileUtil工具类

package com.qfedu.homework;

import java.io.*;

public class FileUtil {
    /**
     *
     * @param start
     * @param end
     * @throws IOException
     */
    public static void copyFile(File start,File end) throws IOException {
        if (!start.isFile()){
            System.out.println("只能拷贝文件");
            throw new IOException("只能拷贝文件");
        }
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(String.valueOf(start))));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(String.valueOf(end))));
        byte[] buf = new byte[4*1024];
        int length;
        while ((length = bis.read(buf)) != -1){
            bos.write(buf,0,length);
        }
        bos.flush();
        bos.close();
        bis.close();
    }
}

当我们需要进行拷贝文件时,可以继承FileUtil类,然后调用copyFile方法,就可以完成功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值