程序员潇然 发表于 2022-8-26 10:08:23

JavaIO之 PipedInputStream 和 PipedOutStream(八)

### 管道简介

!(data/attachment/forum/202208/26/095934mutd3yzhydc1tz9y.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

对于计算机科学中,管道的含义,很久之前就已经出现,用于表示数据直接交互


它的含义与平时说的管道的含义是类似的,就是直连

JavaIO中的 PipedInputStream 和 PipedOutputStream 就是IO体系中字节流的管道

!(data/attachment/forum/202208/26/100014hxy6uyu1m9g9aixk.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

java中,PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流

使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用




大致流程:

我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;

线程B通过读取PipedInputStream中的数据

!(data/attachment/forum/202208/26/100054m74ny7wkah02na6b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


然说是管道,跟现实中的含义有些类似,但是也绝对不能认为他们的数据流方向可以任意

在JavaIO中必须是一个线程通过PipedOutputStream 写入数据;

另外的线程通过与他相连接的PipedInputStream读取数据。



### 实现原理


PipedOutputStream 中有一个 pipedInputStream

pipedInputStream 内部有一个字节数组 通过initPipe方法进行初始化


调用PipedOutputStream的write方法,实际上调用的是内部pipedInputStream 的 receive方法

而 receive方法,操作的正是pipedInputStream内部的字节数组

所以说,只需要使用connect把管道连接起来

就可以通过PipedOutputStream 写入数据,PipedOutputStream读取数据

数据的中转站,正是pipedInputStream 内的数组

!(data/attachment/forum/202208/26/100205f56mj9jpe6ml5ij3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")





### PipedInputStream


PipedInputStream 内部维护了一个字节数组 buffer 默认大小为1024

通过initPipe方法初始化

!(data/attachment/forum/202208/26/100237y4qf4g88gzxhnamf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


PipedOutputStream 和 PipedInputStream 他们其实操作的都是

PipedInputStream 中的buffer

一个读一个写,所以要记住读和写的位置

注意

此处的in和 out 是相对于 PipedInputStream 的buffer[] 来说的

所以in就是 PipedOutputStream 调用write最终使用的

out就是 PipedInputStream 本身read使用的

!(data/attachment/forum/202208/26/100302gp210aqaokknjzsp.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


本文作者:程序员潇然 疯狂的字节X https://crazybytex.com/

想要使用管道流必须要有连接的过程

可以在创建 PipedInputStream 的同时一并连接

或者仅仅创建PipedInputStream 稍后连接

而且,内部字节数组的长度是可以设置的,所以也就是又有了默认的或者设置的两种形式

所以总共有四种形式的构造方法

!(data/attachment/forum/202208/26/100327xawo44plbz4dba3b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

#### read

```java
//读取一个字节
public synchronized int read() throws IOException

//读取长度为len的字节到字节数组b 从偏移量off开始写入
public synchronized int read(byte b[], int off, int len)
```

#### available

获取可用个数

#### close

没有系统资源需要关闭,但是还是有些事情要做

#### connect

connect 调用的是PipedOutputStream中的connect方法

!(data/attachment/forum/202208/26/100508knggeml6p3mbomge.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


### PipedOutputStream

内部需要PipedInputStream

!(data/attachment/forum/202208/26/100526hhahvd1v7qhhfvcd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")



构造方法也比较简单

创建一个PipeOutputStream或者创建的同时进行连接

!(data/attachment/forum/202208/26/100539k9rz4xrur7247g9f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")




PipedInputStream中的connect也是借助于PipedOutputStream

他完成了真正的连接

看得出来,不能重复连接,否则会抛出异常

连接后,会对连接进来的PipedInputStream进行必要的初始化 主要就是 in和 out

另外标记已经连接,也正是用这个connected字段来校验是否已经连接的

!(data/attachment/forum/202208/26/100601y2bqwfb4t4qbbu2q.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


#### write


两个版本的write方法

write(int b) 写入一个字节, 前面24位会被丢弃

write(byte b[], int off, int len) 从指定字节数组的指定位置,读取指定个数的字节, 写入到流

根本还是调用的receive

!(data/attachment/forum/202208/26/100628x2924qobccglc21d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

#### flush


flush 将数据输出,此处不同于文件需要调用操作系统进行写入磁盘

需要通知读线程进行读取

!(data/attachment/forum/202208/26/100659k2kbkk3lxnk33c9b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

#### close

!(data/attachment/forum/202208/26/100711cwhnrt2h8htayky1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")




对于管道流的学习,只需要了解其根本即可

那就是PipedOutputStream 内部指向了一个 PipedInputStream

借助于PipedInputStream 内部的循环数组进行数据缓存,进而达到多线程通信的目的

read 和 write方法的含义用法跟InputStream要求的是一样的,没什么特别的

实现细节有兴趣的可以深入研究

!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-144-1-1.html `
页: [1]
查看完整版本: JavaIO之 PipedInputStream 和 PipedOutStream(八)