Java IO流(二)

1. 缓冲流

1.1 字节缓冲流概述

        当对文件或其他数据源进行频繁的读/写操作时,效率比较低,这时如果使用缓存流就能够更高效地读/写信息。

        比如,可以使用缓冲输出流来一次性批量写出若干数据减少写出次数来提高写出效率。

        如果用生活中的例子做比方,则如下图所示:

        相对于每次都直接从原罐中舀取的操作而言,可以先把物品舀取到一个容器中(相当于缓存),再使用容器去运输。

1.2 BIS 与 BOS

        BufferedInputStream和BufferedOutputStream称为字节缓存流。它们本身并不具有输入/输出流的读取与写入功能,只是在其他流上加上缓存功能提高效率,就像是把其他流包装起来一样,因此,缓存流是一种处理流。

        BufferedInputStream:字节缓存流内置一个缓存区,第一次调用read()方法时尽可能将数据源的数据读取到缓存区中,后续再用read()方法时先确定缓存区中是否有数据,若有则读取缓存区中的数据,当缓冲区中的数据用完后,再实际从数据源读取数据到缓存区中 ,这样可以减少直接读数据源的次数。

        BufferedOutputStream:通过输出流调用write()方法写入数据时,先将数据写入缓存区中,缓存区满了之后再将缓冲区中的数据一次性写入数据目的地。使用缓存字节流可以减少输入/输出操作的次数,以提高效率。

1.3 缓冲流文件复制示例

        编写代码,使用字节缓冲流实现文件复制。代码示意如下:

package api_03;

import java.io.*;

public class FileCopyDemo2 {
    public static void main(String[] args) throws IOException {
        // 随机选取本地一个文件即可,本例中的文件大小为112MB
        FileInputStream fis
                = new FileInputStream("D:/Development/nacos-server-2.0.3.zip");
        BufferedInputStream bis
                = new BufferedInputStream(fis); // 默认缓冲区大小 8192字节


        FileOutputStream fos
                = new FileOutputStream("D:/Development/nacos-server-2.0.3_cp.zip");
        BufferedOutputStream bos
                = new BufferedOutputStream(fos); // 默认缓冲区大小 8192字节

        int d = -1;
        long start = System.currentTimeMillis();
        while((d = bis.read())!=-1) {
            bos.write(d);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时"+(end-start)+"ms"); // 1566ms
        bis.close();
        bos.close();
    }
}

1.4 flush 方法

        输出流缓冲流提供了flush方法:强制将当前缓冲区中已经缓存的字节一次性写出。可以提高数据写出的即时性,但同样也增加了实际写出的次数,一定程度上降低了写出效率。

        在输出流缓冲流的close方法中默认也会调用一次flush方法:保证在关流操作之前清空缓冲区,以避免缓冲区中的数据未能全部输出的情况。

        编写代码,测试 flush 方法。代码示意如下:

package api_03;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BOSFlushDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos
                = new FileOutputStream("./src/api_03/fos2.txt");
        BufferedOutputStream bos
                = new BufferedOutputStream(fos);

        String str = "这是我们输出的文字";
        byte[] data = str.getBytes("utf-8");

        bos.write(data);
        // bos.flush();
        System.out.println("写出完毕!");
        /*
         * 缓冲流关闭前会调用一次flush方法.
         */
        // bos.close();
    }
}

2. 序列化与反序列化

2.1 对象序列化概念

        对象是存在于内存中的,有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这样的操作。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化

        相反,我们有这样一个字节序列需要将其转换为对应的对象,这个过程就称为对象的反序列化。

        如下图所示:

2.2 序列化与反序列化

        序列化是指先将内存中对象的相关信息(包括类、数字签名、对象除transient和static之外的全部属性值,以及对象的父类信息等)进行编码,再传输到数据目的地的过程。

        如果与序列化的顺序相反,就叫反序列化,将序列化的对象信息从数据源中读取出来,并重新解码组装为内存中一个完整的对象。

        如下图所示:

2.3 OIS 与 OOS

        Java中的序列化和反序列化是通过对象流来实现的,分别是ObjectInputStream和ObjectOutputStream。

        ObjectOutputStream:对对象进行序列化的输出流,其实现对象序列化的方法为:

void writeObject(Object o)

        该方法可以将给定的对象转换为一个字节序列后写出 。

        ObjectInputStream:对对象进行反序列化的输入流,其实现对象反序列化的方法为:

Object readObject(),

        该方法可以从流中读取字节并转换为对应的对象。

2.4 Serializable接口

        当使用对象流写入或读取对象时,需要保证对象是可序列化的。这是为了保证能把对象写入文件中,并且能再把对象正确地读回到程序中。一个类如果实现了Serializable接口,那么这个类创建的对象就是可序列化的对象。Java中的包装类和String类均实现了Serializable接口。

        Serializable接口中的方法对程序是不可见的,因此实现该接口的类不需要实现额外的方法,只是作为可序列化的标志。

        如果把一个序列化的对象写入ObjectInputStream中,Java虚拟机就会实现Serializable接口中的方法,将一定格式的数据(对象的序列化信息)写入目的地中。当使用ObjectInputStream从数据源中读取对象时,就会从数据源中读回对象的序列化信息,并根据对象的序列化信息创建一个对象。

2.5 transient关键字

        对象在序列化后得到的字节序列往往比较大,有时我们在对一个对象进行序列化时可以忽略某些不必要的属性,从而对序列化后得到的字节序列”瘦身”。此时,可以对不需要序列化的属性使用关键字 transient:被该关键字修饰的属性在序列化时其值将被忽略。

2.6 序列化示例

        首先,创建示例使用的Person类:包含4个属性,其中一个属性添加transient关键字修饰。代码示意如下:

package api_03;

import java.io.Serializable;
import java.util.Arrays;
public class Person implements Serializable {
    String name;
    int age;
    String gender;
    // 使用 transient修饰的属性不会参与序列化
    transient String[] otherInfo;

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

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

        main方法中添加代码,实现Person 对象的序列化。代码示意如下:

package api_03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializationDemo {
    public static void main(String[] args) throws IOException {
        String name = "苍老师";
        int age = 40;
        String gender = "男";
        String[] otherInfo = {"Java讲师","来自中国","会拍抖音"};

        Person p = new Person(name, age, gender, otherInfo);

        FileOutputStream fos
                = new FileOutputStream("./src/api_03/person.obj");
        ObjectOutputStream oos
                = new ObjectOutputStream(fos);
        /*
        这里流连接的操作分别为:
        1:先将给定对象通过对象流写出,此时对象流会将该对象转换为一组字节,这个过程称
          为对象序列化
        2:序列化后的字节再通过文件流写入了文件,即:写入磁盘中,这个过程称为数据持久
          化
        */
        oos.writeObject(p);
        System.out.println("写出完毕!");
        oos.close();
    }
}

2.7 反序列化示例

        Main方法中添加代码,实现Person 对象的反序列化。代码示意如下:

package api_03;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeSerializationDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis
                = new FileInputStream("./src/api_03/person.obj");

        ObjectInputStream ois
                = new ObjectInputStream(fis);

        Person p = (Person)ois.readObject();
        // otherInfo属性值为null,因为是transient修饰的
        System.out.println(p);
        ois.close();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604376.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多模态EDA论文小记

论文地址 该论文主要改进点是:通过动态化局部搜索中每个集群大小,高斯和柯西分布共同产生个体。总的来说改进点不多,当然也可能是笔者还没发现。 局部搜索 划分集群 划分集群有两个策略分别是: 随机生成一个点作为中心点&…

什么软件可以把视频合并在一起?6个软件教你快速进行视频编辑

什么软件可以把视频合并在一起?6个软件教你快速进行视频编辑 当你需要对视频进行编辑和合并时,选择合适的软件可以极大地提高工作效率和编辑质量。以下是六款被广泛认可且功能强大的视频编辑软件,它们可以帮助你快速、高效地进行视频编辑和合…

PDF转word转ppt软件

下载地址:PDF转word转ppt软件.zip 平时工作生活经常要用到PDF转word转ppt软件,电脑自带的又要开会员啥的很麻烦,现在分享这款软件直接激活就可以免费使用了,超级好用,喜欢的可以下载

C++从入门到精通---模版

文章目录 泛型编程函数模版模版参数的匹配原则类模版类模版的定义格式类模版的实例化 总结 泛型编程 泛型编程是一种编程范式,旨在实现通用性和灵活性。它允许在编写代码时使用参数化类型,而不是具体的类型,从而使代码更加灵活和可重用。 在…

NodeMCU ESP8266 操作 SSD1306 OLED显示屏详解(图文并茂)

文章目录 1 模块介绍2 接线介绍3 安装SSD1306驱动库4 源码分析4.1 硬件兼容性4.2 可能存在的问题总结1 模块介绍 我们将在本教程中使用的OLED显示屏是SSD1306型号:单色0.96英寸显示屏,像素为12864,如下图所示。 OLED显示屏不需要背光,这在黑暗环境中会产生非常好的对比度。…

全面的Partisia Blockchain 生态 4 月市场进展解读

Partisia Blockchain 是一个以高迸发、隐私、高度可互操作性、可拓展为特性的 Layer1 网络。通过将 MPC 技术方案引入到区块链系统中,以零知识证明(ZK)技术和多方计算(MPC)为基础,共同保障在不影响网络完整…

Springboot+Vue项目-基于Java+MySQL的个人云盘管理系统(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…

去除图片水印软件-inpaint

一、普通使用教程 亲眼看看使用 Inpaint 从照片中删除不需要的元素是多么容易: 1.1加载图片 1.2 选择要纠正的问题区域 1.3 告别不需要的对象并保存 二、功能 1 修复旧照片 老并不总是意味着坏。我们拥有的一些旧照片对我们来说仍然很重要,因为它们仍…

FPGA ov5640视频以太网传输

1 实验任务 使用DFZU4EV MPSoC 开发板及双目OV5640摄像头其中一个摄像头实现图像采集,并通过开发板上的以太网接口发送给上位机实时显示。 2 Verilog代码 2.1 顶层模块 timescale 1ns / 1ps //以太网传输视频顶层模块module ov5640_udp_pc (input sys_cl…

威客网上招标系统(五)

目录 5 详细设计 5.1 系统首页 5.1.1系统首页(网站首页index.jsp) 5.1.2 下沙派威客网首页界面说明 5.2 站内新闻信息 5.2.1站内新闻操作界面 5.2.2系统主操作界面说明 5.3威客在线操作界面 5.3.1 威客在线操作界面 5.3.2威客在线说明 5.4系统…

PCIe下一代线缆标准CopprLink发布

作为业界广泛采用的高速串行点对点互联标准,PCIe自诞生以来历经多次迭代升级,现已成为CPU、GPU、FPGA、SSD等计算设备间不可或缺的互连桥梁。PCIe 7.0标准更是将数据传输速率提升至令人惊叹的32 GB/s(每通道)。 然而,面…

[MySQL数据库] Java的JDBC编程(MySQL数据库基础操作完结)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

力扣hot100:199. 二叉树的右视图/437. 路径总和 III(dfs/回溯/树上前缀和/哈希表)

文章目录 一、LeetCode:199. 二叉树的右视图二、LeetCode:437. 路径总和 III 一、LeetCode:199. 二叉树的右视图 LeetCode:199. 二叉树的右视图 差点因为是个中等题打退堂鼓。其实比较简单。 右视图实际上只需要找到&#xff0c…

VitePress快速上手

完整教程:https://blog.share888.top/note/front-end/vitePress/01-vitePress%E5%AE%89%E8%A3%85.html https://blog.share888.top/ VitePress快速上手 官方文档:https://vitepress.dev/zh/guide/markdown VitePress中文网:https://vitejs…

二叉树的基础遍历2.0

1.0入口:二叉树的基础遍历-CSDN博客 在1.0中使用的是简单的结构体建树,本文注重用二维vector建树。 前序,中序和后序的分析1.0已给出,本文不做过多介绍,本文重点讲二叉树的层序遍历。 先奉上前中后序的代码&#xf…

基士得耶(GESTETNER ) CP 6303C 速印机简介

规格参数 产品名称: 基士得耶(GESTETNER ) CP 6303C 速印机 品牌中文: 基士得耶/GESTETNER 型 号: CP-6303C 工作方式: 数码式 制版方式: 自动印刷 制版时间: 曝光玻璃: 31秒(A4长边…

解决windows中的WS Llinux子系统(unbantu2204)访问网络失败问题?

一、问题描述 unbantu先前可以正常访问网络,后面用着用着发现上不了网了, 出现如下异常 Hmm. We’re having trouble finding that site.We can’t connect to the server at www.iqiyi.com.If you entered the right address, you can:Try again late…

xhs 旋转滑块流程分析

声明 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 前言 本文首发于公众号…

[机器学习-01]一文了解|机器学习简介、工具选择和Python包基础应用

目录 前言 正文 01-机器学习简介 (1)诞生过程 (2)人工智能、机器学习和深度学习之间的关系 (3)机器学习核心 02-机器学习工具 (1)Anaconda简介 (2)Jupyte…

基于springboot+vue+Mysql的口腔管理平台

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…