Java IO(三)高级流之缓冲流、对象流

Java IO进阶:缓冲流与对象流详解
本文深入探讨Java的高级流,重点介绍了缓冲流和对象流。缓冲流利用内置8K字节数组提升数据读写效率,通过缓冲流实现文件复制,并讨论了缓冲区的问题。对象流则用于对象的序列化与反序列化,详细解释了如何将Java对象转换为字节序列,以及如何从字节序列恢复对象。

高级流

流连接示意图
请添加图片描述

缓冲流

java.io.BufferedOutputStreamBufferedInputStream
缓冲流是一对高级流,作用是提高读写数据的效率。
缓冲流内部有一个字节数组,默认长度是8K。缓冲流读写数据时一定是将数据的读写方式转换为块读写来保证读写效率。

使用缓冲流完成文件复制操作

请添加图片描述

/**
 * 使用缓冲流完成文件复制操作
 *
 * 缓冲流:
 * java.io.BufferedInputStream和BufferedOutputStream
 * 缓冲流是一对高级流,它们的作用是提高数据的读写效率
 *
 * 缓冲流内部维护一个8K字节数组,无论我们读写方式是什么(随机读写,块读写),缓冲流
 * 都会同一转换成块读写来保证读写效率
 */
public class CopyDemo3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("rainbow.jpg");
        BufferedInputStream bis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream("rainbow_copy.jpg");
        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) + "毫秒");

        bis.close();
        bos.close();

    }
}

缓冲输出流写出数据时的缓冲区问题

通过缓冲流写出的数据会被临时存入缓冲流内部的字节数组,直到数组存满数据才会真实写出一次。

/**
 * 缓冲输出流写出数据的时效性问题(缓冲区问题)
 */
public class BOSDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("demo.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        String line = "摸不到的颜色是否叫彩虹";
        byte[] data = line.getBytes(StandardCharsets.UTF_8);
        bos.write(data);
        /*
            缓冲流的flush可以将缓冲区中已经缓存的数据一次性写出

            flush方法被定义在接口:java.io.Flushable上
            而java.io.OutputStream实现了该接口,而所有的字节输出流都继承自OutputStream
            因此所有的字节输出流都有flush方法.但是不是所有的字节输出流的flush都有实际意义,
            他们的目的大多都只是为了将flush操作传递值缓冲输出流上实际做到写出清空缓冲区的目的.
         */
        bos.flush();
        System.out.println("写出完毕");

        bos.close();
    }
}

flush方法是被定义在了输出流的超类上了,这意味着所有的输出流都有flush 方法,目的是在流连接中传递flush操作给缓冲输出流。 其他高级流的flush中只是调用了它链接的流的flush。
请添加图片描述

对象流

java.io.ObjectOutputStreamObjectInputSteam
对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。
对象序列化:将一个java对象按照其结构转换为一组字节的过程
对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)

对象序列化

对象序列化的流连接操作原理图
请添加图片描述

/**
 * 对象流
 * java.io.ObjectOutputStream和ObjectInputSteam
 * 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化
 *
 * 对象序列化:将一个java对象按照其结构转换为一组字节的过程
 * 对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)
 */
public class OOSDemo {
    public static void main(String[] args) throws IOException {
        /*
            将一个person对象输出到person.obj文件中
         */
        Person p = new Person();
        p.setAge(18);
        p.setGender("男");
        p.setName("Sam");
        p.setOtherInfo(new String[]{"长沙人", "哈哈哈"});

        FileOutputStream fos = new FileOutputStream("person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(p);
        System.out.println("写出完毕!");

        oos.close();
    }
}
/**
 * 使用当前类实例测试对象流的读写操作
 */
public class Person implements Serializable {

    private static final long serialVersionUID = -646586363538177191L;
    private String name;
    private Integer age;
    private String gender;
    private String[] otherInfo;

    public Person() {
    }

    public Person(String name, Integer age, String gender, String[] otherInfo) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.otherInfo = otherInfo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String[] getOtherInfo() {
        return otherInfo;
    }

    public void setOtherInfo(String[] otherInfo) {
        this.otherInfo = otherInfo;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", otherInfo=" + Arrays.toString(otherInfo) +
                '}';
    }
}

对象反序列化

/**
 * 使用对象输入流完成对象的反序列化
 */
public class OISDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /*
            从person.obj反序列化
         */
        FileInputStream fis = new FileInputStream("person.obj");
        ObjectInputStream ois = new ObjectInputStream(fis);

		/*
            Object readObject()
            该方法会进行对象的反序列化,如果对象流通过其连接的流读取的字节分析并非
            是一个java对象时,会抛出异常:ClassNotFoundException
         */
        Person p = (Person) ois.readObject();
        System.out.println(p);
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值