I/O

什么是I/O

I/O 就是InputOutput 的缩写,常见的有文件IO,网络IO,设备IO 等。在linux中所有的组成元素都是一个文件,在文件对于内存来说就是一种流的表现形式。对文件的操作就是对数据流的读写操作,这些读取文件中数据 叫Input流,主要操作 read 函数,往文件中写叫Output流,主要操作 write函数。

主要概念

1 阻塞和非阻塞

阻塞是指数据请求方在请求数据时,被请求方准备完数据的时候系统调用会一直处于等待状态,
非阻塞是指如果被请求方未准备好数据。请求方调用会立即返回,等待完成的信号时再去读取数据。

2 同步与异步

同步是指数据请求方从发起请求到完成整个数据完成时,该请求不会返回,一旦调用返回,请求就结束了,异步是指数据请求方发起指令后就返回,等到被请求方将数据处理好后,再通知到数据的请求方,整个数据 的等待和处理都是被请求一方处理的。

3 I/O 模型

  • 同步阻塞 数据请求方调用请求时 一直等待着返回,直到数据通过原请求返回结束
  • 同步非阻塞 数据请求方调用请求时 ,先做其他请求,每过一段时间会观察是否有返回
  • 异步堵塞 数据请求方调用请求时 一直等待着返回 ,被请求方完成护理后通过回调等方式通知请求方结果
  • 异步非堵塞 数据请求方调用请求时,先做其他请求,被请求方完成护理后通过回调等方式通知请求方结果

传统I/O

InputStream

主要class FileInputStream ByteArrayInputSteam``SocketInputStream`` BufferInputStream

读取操作

1
2
InputStream is = new FileInputStream("../ad/text.txt")
is.read()

OutputStream

主要class FileOuputStream ByteArrayOuputSteam

写入操作

1
2
OutputStream os = new FileOuputStream("../ad/text.txt")
os.write('a')

NI/O

简介

java non-blocking IO 是用来替代传统 IO 的一个方案,可以实现非阻塞式IO模型
主要是由 ChannelsBuffersSelectors 组成。

Channels

有点类似传统IO 的流主要有以下几个区别

  • channel 可以同时读写,但传统IO流只能单向流动
  • channel可以进行异步的读写
  • channel的读写强制使用buffer
    主要实现class
  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

Buffers

使用 channle必定用到buffers,将数据写入到缓冲区时候,缓冲区会记录已经写了多少数据,一但要读取数据的时候 调用filp函数将缓冲区从写入模式改成读取模式,读取后需要用clear 或者 compact函数来清除或者局部清除缓冲区。

Selectors

可以对多个 channel 通道进行监听和处理,通道必须处于非阻塞模式 non-blocking mode

使用简介

读取操作

1
2
3
4
5
RandomAccessFile file = new RandomAccessFile("demo.txt", "rw")  
FileChannel channel = file.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
buffer.flip();

写入操作

1
2
3
4
5
6
7
8
RandomAccessFile file = new RandomAccessFile("demo.txt", "r");  
RandomAccessFile copy = new RandomAccessFile("demoNioCopy.txt", "rw")
FileChannel channel = file.getChannel();
FileChannel writeChannel = copy.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
buffer.flip();
writeChannel.write(buffer, buffer.position());

okio

简介

对传统IO的一层封装,让传统IO更加好用

Sink

Sink对应传统IO的 OutputStream
主要代码

1
2
3
4
5
6
7
8
9
10
11
12
 actual interface Sink : Closeable, Flushable {  
@Throws(IOException::class)
actual fun write(source: Buffer, byteCount: Long)

@Throws(IOException::class)
actual override fun flush()

actual fun timeout(): Timeout

@Throws(IOException::class)
actual override fun close()
}

Source

Source 对应传统IO的 IntputSteam
主要代码

1
2
3
4
5
6
7
8
9
10
interface Source : Closeable {  

@Throws(IOException::class)
fun read(sink: Buffer, byteCount: Long): Long

fun timeout(): Timeout

override fun close()

}

使用简介

读取操作

1
2
3
4
Source fileSource = Okio.source(new File("demo.txt"))  
Buffer buffer = new Buffer();
fileSource.read(buffer, 1024);
System.out.printf(buffer.readByteString().toString());

写入操作

1
2
3
4
Sink sink = Okio.sink(new File("demoCopyOkio.txt"));  
BufferedSink bufferedSink = Okio.buffer(sink);
Source fileSource = Okio.source(new File("demo.txt"))
bufferedSink.writeAll(fileSource);