IO流——字节数组流【内存流】

一、字节数组流概述

1.1 节点流&包装流

 IO流按照处理对象不同来分类,可以分为节点流和包装流。

1)节点流:FileOutputStream、FileInputStream、FileWriter和FileReade

2)包装流:缓冲流、转换流、打印流、数据流和对象流等都属于。

节点流都可以配合包装流来操作,例如:

使用字节流来复制文件效率低,那么我们可以使用缓冲流来提高效率。

使用字节流来存取任意数据类型数据操作繁琐,那么我们可以使用对象流来简化操作等等。

1.2 字节数组流概述

 字节数组流,它也属于节点流

=====================字节数组流分为?================================

1)输入流:ByteArrayInputStream

2)  输出流:ByteArrayOutputStream

=====================小技巧?=======================================

使用字节数组流的时候,为了提高效率和简化操作,可以让字节数组流配合包装流来一起使用

=====================其余节点流和字节数组流的区别?====================

常见的节点流中,例如:FileInputStream和FileReader都是把“文件”当做数据源,而ByteArrayInputStream则是把内存中的“字节数组”当做数据源

=====================字节数组流怎样实现的?===========================

字节数组流,就是和内存中的数组相关的一个流可以将字节数组写到输出流中,也可以将字节数组从输入流中读出来,不涉及磁盘。内存数组输出流可以看成一个可自动扩容的byte数组,可以往里写字节。

=====================字节数组流有什么用?=============================

通过字节数组流,我们可以实现所有数据类型(基本数据类型、引用数据类型)和字节数组之间的转换,然后把转换成字节数组后可以保存到文件或者传输到网络。

二、ByteArrayOutputStream类

ByteArrayOutputStream底层逻辑

ByteArrayOutputStream字节数组输出流在内存中创建一个byte数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。缓冲区初始化时默认32个字节,会随着数据的不断写入而自动增长,但是缓冲区最大容量是2G,只要数据不超过2G,都可以往里写。

数据写出完毕后,可使用toByteArray()方法或toString()方法来获取数据,从而实现了将任意数据类型数据转化为字节数组

例如,给一个字节数组,然后往这个数组中放入各种数据,比如整形、布尔型、浮点型、字符串和对象等,这种需求就可以使用ByteArrayOutputStream来实现。

【示例】将任意数据类型数据转化为字节数组案例

public class ArrayStreamTest {

    public static void main(String[] args) {

        try {

            // 字节数组输出流(节点流),可将任意数据类型转换为字节数组

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            // 缓冲流(包装类),用于提高效率

            BufferedOutputStream bos = new BufferedOutputStream(baos);

            // 对象流(包装流),实现写出任意数据类型

            ObjectOutputStream oos = new ObjectOutputStream(bos);

            // 使用对象流来写数据

            oos.writeInt(123);

            oos.writeDouble(123.45);

            oos.writeChar('A');

            oos.writeBoolean(false);

            oos.writeUTF("node");

            oos.writeObject(new Date());

            // 刷新流,在获取数据之前一定要先刷新流,因为使用了包装流

            oos.flush();

            // 获取数据

            byte[] bs = baos.toByteArray();

            System.out.println(Arrays.toString(bs));

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

通过查看底层源码,我们发现ByteArrayOutputStream类的close()方法并没有实现,所以调用close()方法关闭此流后仍可被使用。

三、ByteArrayInputStream

字节数组输入流就是把一个字节数组 byte[] 包装了一下,使其具有流的属性,可顺序读下去,还可标记跳回来继续读,主要的作用就是用来读取字节数组中的数据。

同理,关闭ByteArrayInputStream无效,调用close()方法在关闭此流后仍可被调用。

【示例】读取上个案例获取的字符数组

public class ArrayStreamTest {

    public static void main(String[] args) {

        try {

            // 获取字节数组,返回上个案例中通过字节数组输出流写出的字节数组

            byte[] bs = outputStreamMethod();

            // 字节数组输入流(节点流),用于读取字节数组中的数据

            ByteArrayInputStream bios = new ByteArrayInputStream(bs);

            // 缓冲流(包装类),用于提高效率

            BufferedInputStream bis = new BufferedInputStream(bios);

            // 对象流(包装流),实现读取指定类型的数据

            ObjectInputStream ois = new ObjectInputStream(bis);

            // 读取数据

            System.out.println(ois.readInt());

            System.out.println(ois.readDouble());

            System.out.println(ois.readChar());

            System.out.println(ois.readBoolean());

            System.out.println(ois.readUTF());

            System.out.println(ois.readObject());

        } catch (IOException e) {

            e.printStackTrace();

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

    }

}

补充,ByteArrayInputStream和ByteArrayOutputStream是字节数组流,那么与之对应的字符数组流则是StringReader和StringWriter。

与字节数组流相比,字符数组流反而用得更少,因为StringBuilder和StringBuffer也能方便的用来存储动态长度的字符,而且大家更熟悉这些类。

猜你喜欢

转载自blog.csdn.net/shengshanlaolin_/article/details/127466119