2021-07-19~2021-07-23总结(Java基础总结五:IO流)

工作总结

工作内容

本周工作内容主要是1.根据角色权限进行数据脱敏(后续会出一篇根据注解形式进行数据脱敏的判断)2.对接客户二维码接口。本周来回顾总结一下Java的IO流。

技术探索

1.浅谈Java IO流
1.1“流”的概念与作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。(通俗来说:数据传输是需要通道的,而IO流就是数据传输的通道。IO流可以形象的比喻为运送货物的传输带。)

IO流的分类
  • 根据操作数据类型的不同可以区分为:字符流与字节流
  • 根据流向的不同可以区分为:输入流与输出流(根据程序为中心,可以将程序读取的数据称之为输入流,程序输出的数据称之为输出流)
IO流结构图

在这里插入图片描述

1.2 字节流与字符流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

1.2.1字符流与字节流的区分
  1. 读写单位不同:字节流以字节8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  2. 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
  3. 读写量不同:字节流:一次读入或读出是8位二进制,字符流:一次读入或读出是16位二进制。(字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!
    (总结:设备上的所有文件都是以二进制的形式存储的,计算机中的最后数据单位就是字节,所有文件最终都是以一个8位的数据单员进行体现,所以字节流可以处理设备上所有的数据只有操作纯文本数据的时候需要优先考虑字符流,其他都使用字节流
1.3 输入流与输出流

输入流只能进行读操作,输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。(输入流:InputStream/Reader 文件到程序输出流:OutputStream/Writer从程序到文件

输入流
  • InputStream 是所有的输入字节流的父类,它是一个抽象类。
  • ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
  • PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
  • ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
输出流
  • OutputStream 是所有的输出字节流的父类,它是一个抽象类。
  • ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
  • PipedOutputStream 是向与其它线程共用的管道中写入数据。
  • ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
BufferedInputStream与BufferedOutputStream

BufferedInputStream和BufferedOutputStream这两个类分别是FilterInputStream和FilterOutputStream的子类,作为装饰器子类,使用它们可以防止每次读取/发送数据时进行实际的写操作,代表着使用缓冲区。
为什么需要缓冲区:不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,提高效率。

  • BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。
  • BufferedInputStream 的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持mark()标记和reset()重置方法。
  • BufferedInputStream 本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据位置。
InputStreamReader与OutputStreamWriter

InputStreamReader: 是字符流Reader的子类,是字节流通向字符流的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如 GBK 等。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。一次只读一个字符。
OutputStreamWriter: 是字符流Writer的子类,是字符流通向字节流的桥梁。每次调用 write()方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。一次只写一个字符。

1.4 代码校验
1.4.1FileInputStream类

代码

    public static void readFile(String filePath) {
        FileInputStream fis=null;
        try{
            //根据文件地址实例化一个文件输入流的对象
            fis=new FileInputStream(filePath);
            //返回字节可以被读取的字节量
            int size = fis.available();
            byte[] btyes = new byte[size];
            //读取数据到数组中
            fis.read(btyes);
            String s = new String(btyes);
            System.out.println(s);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        } finally{
            if (fis!=null){
                try {
                    fis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

结果:
在这里插入图片描述

1.4.2FileOutputStream类
    public static void writeFile(String filePath){
        FileOutputStream fos=null;
        try{
            fos=new FileOutputStream(filePath);
            String s="新增数据123456789";
            byte[] bytes = s.getBytes();
            fos.write(bytes);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (fos!=null){
                try {
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

结果:
在这里插入图片描述
代码(通过 FileInputStream、FileOutputStream实现文件复制以及迁移)

    public static void copyFile(String filePath,String newFilePath) {
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try{
            //根据文件地址实例化一个文件输入流的对象
            fis=new FileInputStream(filePath);
            //返回字节可以被读取的字节量
            int size = fis.available();
            byte[] btyes = new byte[size];
            //读取数据到数组中
            fis.read(btyes);
            fos = new FileOutputStream(newFilePath);
            fos.write(btyes);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        } finally{
            if (fis!=null){
                try {
                    fis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if (fos!=null){
                try {
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
1.4.3BufferedInputStream与BufferedOutputStream类
    public static void copyFile(String filePath,String newFilePath){
        InputStream is=null;
        OutputStream os=null;
        BufferedInputStream bis=null;
        BufferedOutputStream bos=null;
        try{
            is=new FileInputStream(filePath);
            bis=new BufferedInputStream(is);
            os = new FileOutputStream(newFilePath);
            bos=new BufferedOutputStream(os);

            byte[] bytes = new byte[1024];
            int length=0;
            while ((length=bis.read(bytes))!=-1){
                bos.write(bytes,0,length);
            }
            //缓冲区内容写入文件
            bos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
        if (bos!=null){
            try{
                bos.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        if (bis!=null){
            try{
                bis.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        if (is!=null){
            try{
                is.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        if (os!=null){
            try{
                os.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
1.4.4InputStreamReader与OutputStreamWriter类
    private static void copyFile(String filePath,String newFilePath){
        InputStream inputStream = null ;
        InputStreamReader inputStreamReader = null ;

        OutputStream outputStream = null ;
        OutputStreamWriter outputStreamWriter = null ;

        try {
            inputStream = new FileInputStream( filePath ) ; //创建输入流
            inputStreamReader = new InputStreamReader( inputStream ) ; //创建转换输入流

            outputStream = new FileOutputStream( newFilePath ) ; //创建输出流
            outputStreamWriter = new OutputStreamWriter( outputStream ) ; //创建转换输出流

            int result = 0 ;

            while( (result = inputStreamReader.read()) != -1){  //一次只读一个字符
                outputStreamWriter.write( result ); //一次只写一个字符
            }

            outputStreamWriter.flush();  //强制把缓冲写入文件

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{

            if ( outputStreamWriter != null) {
                try {
                    outputStreamWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if ( inputStreamReader != null ) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

以上有关异常的内容是阅读了,该文章的学习总结。

总结

1、本周对Java得IO流进行了回顾在平时使用工具类比较多,所有有所忽略IO流的实现过程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值