IO流知识汇总

一、IO流的定义

水管承载的是水,油管承载的是油,io流中承载是数据,是数据的载体。

1.按流的方向分:输入流、输出流

以jvm作为参照,将数据从外部读入到jvm中称为输入流;将数据从jvm写入到外部称为输出流。

2.按流的数据单位分:字节流、字符流

字节流可以传输所有的数据,如文本、图片、音频、视频。字符流专门传输文本。

3.按流的功能流:节点流、过滤流

节点流是专门完成传输功能的流,过滤流是对节点流进行增强的流。

二、字节流

操作的是字节,字节流的抽象基类InputStream、OutputStream。

1.FileInputStream:

int read():每次从文件中读一个字节,并且把读到的内容返回。返回的是字节对应的ascii码值。

int read(byte[] b):从文件中读b.length个字节到b数组中,返回实际读取到的字节数。

int read(byte[] bs, int off, int len):从文件中读取多个字节存储到bs数组中,len为读取的字节个数,字节在数组的存储位置由off,len决定。返回实际读取到的字节数。

2.FileOutputStream:

void write(int v) : 写入一个字节,int类型的最后一个字节。

void write(byte[] bs) : 写入一个数组。

void write(byte[] bs, int off, int len) :写入数组的一部分,内容由off、len决定。

3.异常处理

使用try…catch... finally规范io流书写过程。

字节流代码示例:

    public static void main(String[] args) throws IOException {
        //读单个字节
        readSingle();

        //读多个字节到字节数组
        readBytes();

        //读多个字节到字节数组的指定位置
        readBytesByCondition();
        
        //写一个字节数组到io流中
        writeBytes();
    }

    private static void writeBytes() {
        //规范化异常处理过程
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream("D:/writer.txt");
            String str = "hello world";
            byte[] bytes = str.getBytes();
            //将字节数组写入io流中
            outputStream.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void readBytesByCondition() throws IOException {
        InputStream inputStream = new FileInputStream("D:/iotest.txt");
        byte[] b = new byte[6];
        //读取多个字节到字节数组中
        while ((inputStream.read(b, 1, 5)) != -1) {
            System.out.println(new String(b, "gbk"));
            b = new byte[6];
        }
        inputStream.close();
    }

    private static void readBytes() throws IOException {
        InputStream inputStream = new FileInputStream("D:/iotest.txt");
        byte[] b = new byte[6];
        //读取多个字节到字节数组中
        while ((inputStream.read(b)) != -1) {
            System.out.println(new String(b, "gbk"));
        }
        inputStream.close();
    }

    private static void readSingle() throws IOException {
        FileInputStream inputStream = new FileInputStream("D:\\iotest.txt");
        //读取一个字节并返回
        int ch;
        while ((ch = inputStream.read()) != -1) {
            System.out.println(ch);
        }
        inputStream.close();
    }

4.字节过滤流(字符过滤流类似)

关键在于过滤流增强了什么功能,以及在什么情况下要使用过滤流功能。字节过滤流的基类是FilterInputStream,FilterOutputStream。

特征:

1.创建过滤流时需要先创建节点流。节点流才具备数据传输功能。

2.一个节点流可以被多个过滤流封装。

3.关闭流时,只需要关闭最外层,内层流会随着外层流的关闭而关闭。

下面介绍下常用的过滤流:

BufferedOutputStream/BufferedInputStream

增强点:增强了缓冲区的功能。一般来说,每一次的read,write都是一次io操作,需要跨越jvm的边界,因此非常耗性能。通过引入缓冲机制,对于每次的读写,不直接进行io操作,而是操作缓冲区,减少io交互次数。写的时候先往buffer数组中写入,buffer数组满了后进行io操作。读的时候先从流中读buffer.length个字节到buffer数组,然后从buffer数组中读数据。

底层实现:底层是一个字节数组,用于存读写的数据。

以字节输出流为例,缓冲区数据写入文件时机:1.缓冲区已满(待写入字节长度大于字节数组长度)。2.调用close方法,关闭io流。3.调用flush方法,清空缓冲区。

DataOutputStream/DataInputStream

增强点:增强了8种基本类型和字符串的读写功能,能够写int,double等数值,文件类型为.dat。

底层实现:底层会将基本类型做字节的拆分,比如double类型会被拆分成8个字节,在写入到io流中。

PrintStream

增强点:1.缓冲区功能;2.写8中基本类型和字符串数据功能;3.写对象。

底层实现:引用了BufferedWriter,print方法,写基本类型还写对象的本质是写对应的字符串。

5.ObjectOutputStream/ObjectInputStream

增强点:1.缓冲区功能;2.读写基本类型和字符串数据功能;3.读写对象。文件类型为.ser

底层实现:底层使用了字节数组实现缓冲功能;写基本类型数据和data流相同,使用了data流。

序列化:把对象放在流上进行传输的过程,成为“对象序列化”。一个对象如果能在留上传输,我们称这个对象是可序列化的。如果某个字段不需要序列化,使用transient修饰。

6.ByteArrayOutputStream/ByteArrayInputStream

ByteArrayOutputStream:

内存操作流,write方法操作的字节在内存中,通过writeTo方法可以写入文件。

toByteArray和toString可输出内置缓冲区的内容。

内置缓冲区数组,长度不够时会扩容到原来的两倍。

ByteArrayInputStream:

将字节内容通过构造方法存入流的缓冲区中。

从缓冲区读流的内容。

 

三、字符流

操作的是字符,Reader、Writer是字符流的抽象基类。

FileReader,FileWriter是基础的字符流。

1.字符编码

编码:字符转换成数字(二进制)的过程。

解码:数字转换成字符的过程。

2.编码规范

世界上任何一种编码方式,都与 ASCII 编码兼容,也就是说,任何 一种编码方式下面, A都对应65,a都对应97,没有例外。

ASCII:最早的编码方式,规定了英文字母和英文标点对应的编码。

ISO-8859-1:规定了西欧字符和西欧标点对应的编码。

GBK:规定了简体中文对应的编码,Windows系统默认编码方式。

Big5:规定了繁体中文对应的编码,台湾地区使用广泛。

UTF-8:国际通用的编码方式,包含了简体中文和繁体中文。注意,同一个汉字在GBK和UTF-8两种编码方式下编码是不同的。

3.乱码问题:

本质:编码解码的方式不一致。

//获取系统默认的编码格式
System.out.println(System.getProperty("file.encoding"));
System.out.println(Charset.defaultCharset());

4.桥转换

字节流转换为字符流。通过桥转换可以指定io流的编码方式。InputStreamReader,OutputStreamWriter。

桥转换的步骤:

1.创建字节流。

2.桥转换为字符流,可指定编码方式。

3.在字符流的基础上可封装过滤字符流。

4.读写数据。

5.关闭外层流。

5.字符过滤流

常用的字符过滤流有BufferedReader(增强是缓冲区)第一次读先将读到的内容放入到buf数组,默认8192个长度,后续都是从buf数组中读数据。当buf数组中的内容读完后,继续从流中读入buf数组。PrintWriter(1.增强缓冲区;2.支持基本数据类型的输出,以字符形式输出,注意和data流的区别;3.写对象,以字符形式输出)。

    private static void readLine() throws IOException {
        //创建字节流
        InputStream inputStream = new FileInputStream("d://string.txt");
        //通过桥转换转为字符流
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "GBK");
        //封装过滤流
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        //读数据
        String content = null;
        while((content = bufferedReader.readLine())  != null ) {
            System.out.println(content);
        }
        //关闭外层流
        bufferedReader.close();
    }
    private static void printStr() throws Exception {
        //当做过滤流使用
        OutputStream outputStream = new FileOutputStream("d://print.txt");
        Writer out = new OutputStreamWriter(outputStream);
        PrintWriter writer = new PrintWriter(out);
        writer.println("我在清华园");
        writer.println("我在tl");
        writer.println("我在技术部");
        writer.close();
        //当做节点流使用,内部做了包装
        PrintWriter writer1 = new PrintWriter("d://print1.txt");
        writer1.println("我是谁");
        writer1.close();
        //当做桥转换使用
        PrintWriter writer2 = new PrintWriter(new FileOutputStream("d://print2.txt"));
        writer2.println("我在哪里");
        writer2.close();
    }

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值