Java高级流

高级流

java将IO分为了两类

  • 节点流:又称为"低级流"
    • 特点:直接链接程序与另一端的"管道",是真实读写数据的流
    • IO一定是建立在节点流的基础上进行的。
    • 文件流就是典型的节点流(低级流)
  • 处理流:又称为"高级流"
    • 特点:不能独立存在,必须链接在其他流上
    • 目的:当数据经过当前高级流时可以对数据进行某种加工操作,来简化我们的同等操作
    • 实际开发中我们经常"串联"一组高级流最终到某个低级流上,使读写数据以流水线式的加工处理完成。这一操作也被称为使"流的链接"。流链接也是JAVA IO的精髓所在。
缓冲流

java.io.BufferedInputStreamBufferedOutputStream

功能

在流链接中的作用:加快读写效率

通常缓冲是最终链接在低级流上的流

构造器
  • 缓冲字节输出流

    java 复制代码
    BufferedOutputStream(OutputStream out)
    实例化一个缓冲字节输出流并链接在指定的字节输出流上。默认缓冲区大小8kb(内部维护的byte[] buf数组长度8192)
    
    BufferedOutputStream(OutputStream out,int size)
    实例化一个指定缓冲区大小的缓冲字节输出流并链接在指定的字节输出流上。
  • 缓冲字节输入流

    java 复制代码
    BufferedInputStream(InputStream in)
    实例化一个缓冲字节输入流并链接在指定的字节输入流上。默认缓冲区大小8kb(内部维护的byte[] buf数组长度8192)
    
    BufferedInputStream(InputStream in,int size)
    实例化一个指定缓冲区大小的缓冲字节输入流并链接在指定的字节输入流上。    
java 复制代码
package io;

import java.io.*;

/**
 * 使用缓冲流完成文件复制操作
 */
public class CopyDemo3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("image.png");
        BufferedInputStream bis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream("image_cp3.png");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int d;
        long start = System.currentTimeMillis();
        while((d=bis.read())!= -1){
            bos.write(d);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时:"+(end-start)+"ms");
        bis.close();
        bos.close();

    }
}
原理

内部定义了一个属性byte buf[]。它等同于我们之前练习复制案例时的块写操作。

并且默认创建时,该buf数组的长度为8192(8kb)长度。

缓冲流在读写数据时总是以块读写数据(默认是8kb)来保证读写效率的

缓冲流提供了多种构造器,可以自行指定缓冲区大小。

写缓冲问题

由于缓冲输出流会将写出的数据装满内部缓冲区(默认8kb的字节数组)后才会进行一次真实的写出操作。当我们的数据不足时,如果想要及时写出数据,可以调用缓冲流的flush()方法,强制将缓冲区中已经缓存的数据写出一次。

java 复制代码
package io;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * 缓冲输出流的写缓冲问题
 */
public class BosFlushDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("bos.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        String line = "super idol的笑容都没你的甜~";
        byte[] data = line.getBytes(StandardCharsets.UTF_8);
        bos.write(data);
        /*
            void flush()
            强制将缓冲流的缓冲取(内部维护的字节数组)中已经缓存的字节一次性写出
         */
//        bos.flush();
        System.out.println("写出完毕!");
        bos.close();//缓冲输出流的close()方法内部会自动调用一次flush()方法确保数据写出
    }
}
flush的传递

flush()方法是被定义在java.io.Flushable中。而字节输出流的超类java.io.OutputStream实现了

该接口,这意味着所有的字节输出流都有flush方法。而除了缓冲流之外的高级流的flush方法作用就是调用它链接的流的flush方法将该动作传递下去。最终传递给缓冲流来清空缓冲区。

对象流

java.io.ObjectInputStreamObjectOutputStream

作用
  • 对象输出流:将我们的java对象进行序列化
  • 对象输入流:将java对象进行反序列化
序列化

将一个对象转换为一组可被传输或保存的字节。这组字节中除了包含对象本身的数据外,还会包含结构信息。

序列化的意义

实际开发中,我们通常会将对象

  • 写入磁盘,进行长久保存
  • 在网络间两台计算机中的java间进行传输

无论是保存在磁盘中还是传输,都需要将对象转换为字节后才可以进行。

对象输出流的序列化操作
java 复制代码
void writeObject(Object obj)
将给定的对象转换为一组可保存或传输的字节然后通过其链接的流将字节写出
例:
java 复制代码
package io;

import java.io.*;

/**
 * 对象流
 * 使用对象输出流完成对象序列化操作并最终保存到文件person.obj中
 */
public class OOSDemo {
    public static void main(String[] args) throws IOException {
        String name = "张三";
        int age = 18;
        String gender = "女";
        String[] otherInfo = {"黑","壮实","java技术好","来自鄂尔多斯"};
        Person p = new Person(name,age,gender,otherInfo);
        FileOutputStream fos = new FileOutputStream("person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        /*
            对象输出流提供的序列化对象方法:
            void writeObject(Object obj)
            将给定的对象转换为一组可保存或传输的字节然后通过其链接的流将字节写出

            序列化对象时要求该对象对应的类必须实现接口:java.io.Serializable
            如果写出的对象对应的类没有实现该接口,那么writeObject会抛出下面异常
            java.io.NotSerializableException

         */
        oos.writeObject(p);
        System.out.println("对象写出完毕");
        oos.close();
    }
}
序列化要求

对象输出流要求写出的对象必须实现接口:java.io.Serializable

上述案例中我们看到,如果写出的对象Person没有实现java.io.Serializable时会抛出异常:

java.io.NotSerializableException

相关推荐
救救孩子把1 分钟前
Java基础之IO流
java·开发语言
WG_172 分钟前
C++多态
开发语言·c++·面试
小菜yh3 分钟前
关于Redis
java·数据库·spring boot·redis·spring·缓存
宇卿.9 分钟前
Java键盘输入语句
java·开发语言
浅念同学9 分钟前
算法.图论-并查集上
java·算法·图论
Amo Xiang19 分钟前
2024 Python3.10 系统入门+进阶(十五):文件及目录操作
开发语言·python
立志成为coding大牛的菜鸟.22 分钟前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞23 分钟前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
friklogff32 分钟前
【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
开发语言·c#·区块链
重生之我在20年代敲代码2 小时前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记