okio篇2-RealBufferedSource

news2024/11/24 17:39:30

上一篇讲过,okio只有两个概念,source和sink。source对应InputStream,即负责将数据读出,是一个输出方(所以只有source.read方法)。sink对应outputStream,负责获取数据写入,是一个写入方(所以只有sink.write方法)。而对于,source.read(sink)这个方法,实际就是,将source中的数据读出,写入到sink当中。

所以其实source和sink只有数据的流向不一致。所以,这里只介绍了RealBufferedSource,实际是跟RealBufferedSink是一致的。

介绍RealBufferedSource,首先先看下okio的基础用法。

public void readFileUseOkIo() {
    try {
        BufferedSource source = Okio.buffer(Okio.source(new File(fileName)));
        String content;
        while ((content = source.readUtf8Line()) != null) {
            System.out.println("readFileUseOkIo content:"+content);
        }
        source.close();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

注意,一般对应okio,只有两个常用的api,okio.source和okio.buffer方法。

这一行的实际含义是:

创建new File,内部创建new FileInputStream,作为source对应的inputStream。

再调用buffer,将source传入RealBufferedSource。RealBufferedSource同时维护一个Buffer,和一个Source。

Okio.source

source方法接收一个InputStream。并返回一个新创建的Source,重写了read(Buffer,long)方法。

这个方法在哪里会被调用到呢?后面会讲到。先记住source方法实际是重写了read(Buffer,long)方法。

// Okio.Source
private static Source source(final InputStream in, final Timeout timeout) {
    if (in == null) {
        throw new IllegalArgumentException("in == null");
    } else if (timeout == null) {
        throw new IllegalArgumentException("timeout == null");
    } else {
        return new Source() {
            // 这里实际上,是从source中的buffer转移数据到sink当中,如果source中没有数据了,
            // 就从in中读取数据到source中的buffer
            public long read(Buffer sink, long byteCount) throws IOException {
                if (byteCount < 0L) {
                    throw new IllegalArgumentException("byteCount < 0: " + byteCount);
                } else if (byteCount == 0L) {
                    return 0L;
                } else {
                    try {
                        timeout.throwIfReached();
                        // 从sink中获取一个可写的segment
                        Segment tail = sink.writableSegment(1);
                        int maxToCopy = (int)Math.min(byteCount, (long)(8192 - tail.limit));
                        // 从in中获取tail中可容纳的空间个字节到tail中
                        int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
                        if (bytesRead == -1) {
                            return -1L;
                        } else {
                            tail.limit += bytesRead;
                            sink.size += (long)bytesRead;
                            return (long)bytesRead;
                        }
                    } catch (AssertionError var7) {
                        if (Okio.isAndroidGetsocknameError(var7)) {
                            throw new IOException(var7);
                        } else {
                            throw var7;
                        }
                    }
                }
            }

            public void close() throws IOException {
                in.close();
            }

            public Timeout timeout() {
                return timeout;
            }

            public String toString() {
                return "source(" + in + ")";
            }
        };
    }
}

Okio.buffer

// Okio.buffer方法
public static BufferedSource buffer(Source source) {
    return new RealBufferedSource(source);
}

Okio.buffer方法,只简单返回了RealBufferSource方法。

RealBufferedSource实际上是一个Source类型,内部维护了一个Buffer和一个Source。这个Source参数,实际就是刚才okio.source方法新创建的new Source,这个source重写了read(Buffer,long)方法。

// RealBufferedSource.read
// 两个Buffer之间转移,比如Source.read(Sink,byteCount)的时候,会调用这个方法
public long read(Buffer sink, long byteCount) throws IOException {
    if (sink == null) {
        throw new IllegalArgumentException("sink == null");
    } else if (byteCount < 0L) {
        throw new IllegalArgumentException("byteCount < 0: " + byteCount);
    } else if (this.closed) {
        throw new IllegalStateException("closed");
    } else {
        long read;
        if (this.buffer.size == 0L) {// 从这里看出,实际就是先从source读Segment.Size个字节的数据到buffer
        // 注意这里,这里实际是okio.source方法那里重写的read方法
        // 即这里,如果buffer内数据为空,就会调用stream.read方法,将数据读到buffer,即RealBufferedSource也是一个缓冲区。
            read = this.source.read(this.buffer, 8192L);
            if (read == -1L) {
                return -1L;
            }
        }

        read = Math.min(byteCount, this.buffer.size);
        // 然后再从buffer读取read个字节的数据到sink。一次最多只读取一个Segment的数据
        return this.buffer.read(sink, read);
    }
}

RealBufferedSource方法也重写了read(Buffer,long)。这个方法一般用于buffer间的数据交互,比如source的buffer数据,转移到sink的buffer中。

从上面的注释可以看出:

RealBufferSource中持有Source(Stream)和Buffer,Buffer相当于Source的缓冲区,Sink直接跟Buffer进行数据交互。当Buffer中数据被读取完了,Buffer会从Source中读数据。

也即:

总结

okio对外暴露的接口:okio.source和okio.buffer。

其中okio.source,构建了stream到buffer的数据流向。

而okio.buffer,创建了RealBufferedSource。RealBufferedSource维护一个buffer。当需要将数据传给sink的时候,优先从buffer中读取数据到sink。如果buffer为空,就会调用okio.source的方法,从stream中读取数据到buffer。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RT-Thread Nano在keil Simulator中的仿真

目的&#xff1a;使用STM32CubeMX生成包含RT-Thread Nano内核和FinSH控制台的keil工程&#xff0c;在没有硬件开发板的情况下&#xff0c;通过keil Simulator来运行系统&#xff0c;并通过SHELL来与系统进行交互。 一、使用STM32CubeMX生成RT-Thread Nano工程 官方文档已经说…

C++标准库 -- 动态内存 (Primer C++ 第五版 · 阅读笔记)

C标准库 --动态内存 (Primer C 第五版 阅读笔记&#xff09; 第12章 动态内存------(持续更新)12.1、动态内存与智能指针12.1.1、shared_ptr类12.1.2、直接管理内存12.1.3、shared_ptr和new结合使用12.1.4、智能指针和异常12.1.5、unique_ptr12.1.6、weak_ptr 12.2、动态数组1…

网络通信之网络层与数据链路层

文章目录 讲在前面网络层网络层概述IP协议格式网段划分公有IP、私有IP、特殊IP理解路由 数据链路层MAC地址以及MAC帧&#xff08;以太网帧&#xff09;MTU协议MTU对IP和TCP协议的影响ARP协议及其作用 涉及到的相关协议DNS协议&#xff08;应用层&#xff09;NAT与NAPT协议 总结…

BEV (0)---DETR

1 DETR 1.1 DETR处理流程 1.1.1 将图像输入给Backbone获得图像特征与位置编码 ①. 对给定的输入图像通过resnet进行特征提取&#xff0c;最终得到特征图C5∈RBx2048xhxw,其中h、w为输入图像尺寸得1/32。随后再用一层11卷积压缩一下通道&#xff0c;得到特征图P5∈RBx256xhxw。…

jvm调优策略

jvm调优主要是内存管理方面的调优&#xff0c;包括各个代的大小&#xff0c;GC策略等。 代大小调优 JVM 中最大堆大小有三方面限制&#xff1a;相关操作系统的数据模型&#xff08;32-bt还是64-bit&#xff09;限制&#xff1b;系统的可用虚拟内存限制&#xff1b;系统的可用物…

数据结构学习记录——什么是堆(优先队列、堆的概念、最大堆最小堆、优先队列的完全二叉树表示、堆的特性、堆的抽象数据类型描述)

目录 优先队列 若采用数组或链表实现优先队列 数组 链表 有序数组 有序链表 总结 若采用二叉搜索树来实现优先队列 最大堆 堆的概念 优先队列的完全二叉树表示 堆的两个特性 结构性 有序性 【例】最大堆和最小堆 【例】不是堆 堆的抽象数据类型描述 优先队列…

安排超市 -- BFS分割搜索

4.安排超市 给定一个n*n的地图。地图是上下左右四联通的&#xff0c;不能斜向行走&#xff1a; *代表障碍&#xff0c;不可通行。 .代表路&#xff0c;可以通行。 #代表房子。房子也是可以通行的。 小红现在需要在一些地方安排一些超市&#xff08;不能安排在障碍物上&#xf…

山东专升本计算机第七章-计算机网络基础

计算机网络基础 计算机网络系统 考点 6 计算机网络硬件 主体设备 • 称为主机 • 一般可分为中心站&#xff08;又称服务器&#xff09;和工作站&#xff08;客户机&#xff09; 连接设备 • 网卡 • 工作在数据链路层 • 网卡又称网络适配器&#xff0c;是连接主机和网…

【C++初阶】引用

一.概念 引用就是取别名&#xff0c;在语法上它不会开空间&#xff0c;而是和它引用的变量共用同一块空间。对引用的操作也就是对原来变量的操作。就像现实生活中给人取外号一样&#xff0c;不管是喊外号还是本名&#xff0c;指的都是那个人。 二.引用特性 1.引用类型必须和引用…

Java8 新特性讲解

一、Lambda表达式 Lambda 是一个匿名函数&#xff0c;我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格&#xff0c;使Java的语言表达能力得到了提升。 二、函数式接口 &#…

【网课平台】Day15.Devops:持续集成与持续交付

文章目录 一、Devops1、什么是Devops2、什么是CI/CD3、Devops方案参考 二、人工部署1、项目打jar包2、生成镜像、创建容器 三、自动化部署1、代码提交到git2、修改pom.xml文件3、前端部署 一、Devops 1、什么是Devops 一个软件的生命周期包括&#xff1a;需求分析阶、设计、开…

SpringCloud:ElasticSearch之集群

单机的elasticsearch做数据存储&#xff0c;必然面临两个问题&#xff1a;海量数据存储问题、单点故障问题。 海量数据存储问题&#xff1a;将索引库从逻辑上拆分为N个分片&#xff08;shard&#xff09;&#xff0c;存储到多个节点单点故障问题&#xff1a;将分片数据在不同节…

【原创】运维的终点是开发~chatGPT告诉你真相

文章目录 软件技术岗位鄙视链&#xff0c;你在哪层呢&#xff1f;让chatGPT告诉你运维工作好&#xff0c;还是开发工作好问它几个问题1. 一个三年运维成长的案例和薪资2. 一个三年开发成长的案例和薪资3. 一个五年运维成长的案例和薪资4. 一个五年开发成长的案例和薪资5. 一个十…

云分析迁移:顺应需求

云提供了对新分析功能、工具和生态系统的访问&#xff0c;可以快速利用这些功能、工具和生态系统来测试、试点和推出新产品。然而&#xff0c;尽管迫在眉睫&#xff0c;但企业在将分析迁移到云时仍感到担忧。组织正在寻找能够帮助他们分配资源和集成业务流程的服务提供商&#…

Linux 服务器上安装和使用 Redis,只需这 4 步!

一、使用 yum 安装 Redis 使用以下命令&#xff0c;直接将 redis 安装到 linux 服务器&#xff1a; yum -y install redis 二、配置远程连接 a&#xff09;首先第一步&#xff0c;将 redis 配置文件下载到本地&#xff08;如果你熟悉 vim 操作&#xff0c;直接用 vim 编辑即可…

论文阅读《PIDNet: A Real-time Semantic Segmentation Network Inspired by PID》

论文地址&#xff1a;https://arxiv.org/pdf/2206.02066.pdf 源码地址&#xff1a;https://github.com/XuJiacong/PIDNet 概述 针对双分支模型在语义分割任务上直接融合高分辨率的细节信息与低频的上下文信息过程中细节特征会被上下文信息掩盖的问题&#xff0c;提出了一种新的…

【五一创作】Springboot+多环境+多数据源(MySQL+Phoenix)配置及查询(多知识点)

文章目录 1. 背景2. 技术点3 子模块依赖SpringBoot设置4. 多环境配置4.1 application.yml4.2 application-pro.yml 5. 多数据源配置5.1 yml配置5.2 自定义数据源在Java中配置5.2.1 PhoenixDataSourceConfig5.2.2 MysqlDataSourceConfig 6. 完整的Pom6. 测试6.1 Mapper配置6.2 方…

字符、块、网络设备

设备模型&#xff08;的意义&#xff09; 降低设备多样性带来的Linux驱动开发的复杂度&#xff0c;以及设备热拔插处理、电源管理等&#xff0c;Linux内核提出了设备模型概念。设备模型将硬件设备归纳、分类&#xff0c;然后抽象出一套标准的数据结构和接口。驱动的开发&#…

Java项目上线之云服务器环境篇(四)——Redis的安装与配置

Java项目上线之云服务器环境篇&#xff08;四&#xff09;——Redis的安装与配置 在我们的项目里可能会用到Redis缓存&#xff0c;需要对Redis进行简单的配置。 1、我们的redis最好放在一个事先安装好的文件夹里&#xff0c;这样更方便于管理。 例如&#xff1a; redis我是放在…

前端开发:JS的事件循环执行机制详解

前言 在前端开发中&#xff0c;涉及到JS原生的使用原理是非常重要的知识点&#xff0c;尤其是在实际工作过程中会遇到各种复杂的业务需求场景&#xff0c;以及具体开发中可能会遇到一些涉及基于JS原理的使用&#xff0c;这都要求开发者能够很好的了解和掌握JS原生的常用原理。J…