美文网首页
Java I/O相关

Java I/O相关

作者: 一一道长一一 | 来源:发表于2016-05-20 17:06 被阅读34次

I/O类的结构体系

I/O体系包含字节流、字符流、文件流和一个接口Serializable

字节流包含输入流InputStream和输出流OutputStream。

字符流包含输入流Reader和输出流Writer。

文件指的就是File对象。

另外还有一个自我独立的类:RandomAccessFile。

1.New I/O和I/O的区别

NIO和IO之间第一个最大的区别是,标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

IO是阻塞的,NIO是非阻塞的(可以异步调用)。

NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

2.New I/O的新特性

NIO包(java.nio.*)引入了四个关键的抽象数据类型,它们共同解决传统的I/O类中的一些问题。

1. Buffer:它是包含数据且用于读写的线形表结构。其中还提供了一个特殊类用于内存映射文件的I/O操作。Buffer的主要实现有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer。

2. Charset:它提供Unicode字符串影射到字节序列以及逆影射的操作。

3. Channels:包含socket,file和pipe三种管道,它实际上是双向交流的通道。主要Channel的实现有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel。

4. Selector:它将多元异步I/O操作集中到一个或多个线程中(它可以被看成是Unix中select()函数或Win32中WaitForSingleEvent()函数的面向对象版本)。

NIO类之间的关系:如果想把一个字节数组写到文件中去,就应该使用ByteBuffer.wrap()方法把字节数组包装起来,然后用getChannel()方法在FileOutputStream上打开一个通道,接着将来自于ByteBuffer的数据写到FileChannel中。(ByteBuffer是将数据移进移出通道的唯一方式)。

MappedByteBuffer可以用来读写因为太大而不能放入内存的文件,所以叫做内存映射文件。

3.NIO Buffer的深入理解

1.通过Buffer的allocate方法,可以给Buffer分配空间。

2.Buffer的capacity(容量),position(当前读或写到的位置)和limit(写模式下等于capacity,读模式时的值等于写模式下的position)。

3.flip()方法将Buffer从写模式切换到读模式,执行的操作为:position=0;limit = 写模式的position。意思为可读取已经写入的所有内容。

4.clear()方法将Buffer从读模式切换到写模式,执行的操作为:position=0;limit=capacity。clear()方法并未清空Buffer中的数据,如果Buffer中有未读的数据,调用clear()后数据会被遗忘。

5.compact()方法与clear()方法不一样的地方是当Buffer中有未读的数据的时候,compact()方法会将未读的数据,将position设置为最后一个未读元素的后边,limit=capacity。意思是Buffer准备好写数据了,但不会覆盖未读的数据。

6.rewind()方法是将position设置为0,limit保持不变。意思是可以重新读取Buffer中的数据。

7.mark()和reset()方法,mark()方法可以标记一个position,等执行完所需的操作后,调用reset()方法可以将position恢复到mark的position。意思是可以重复读取Buffer中的某一段。

4.NIO的聚集

Channel的read和write方法可以接受一个Buffer的数组参数,可以将数据写到多个Buffer中或从多个Buffer中读取数据。适用于分开读取信息头部和信息主体。

5.Selector

与Selector一起使用时,Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。

Channel的register()的第二个参数是一个interest集合,意思是在通过Selector监听Channel时对什么事件感兴趣,可以监听四种不同类型的事件:SelectionKey.OP_CONNECT(连接就绪)、SelectionKey.OP_ACCEPT(接收就绪)、SelectionKey.OP_READ(读就绪)、SelectionKey.OP_WRITE(写就绪)。通道触发了一个事件意思就是这个事件已经就绪。

如果不止对一种事件感兴趣,可以使用‘位或’操作,如  int   interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

用“位与”操作interest 集合和给定的SelectionKey常量,可以确定某个确定的事件是否在interest 集合中。如:boolean  isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;

当向Selector注册Channel时,register()方法会返回一个SelectionKey对象,这个对象包含了:interest集合、ready集合、Channel、Selector、附加的对象(可选)。

ready 集合是通道已经准备就绪的操作的集合,selectionKey.isAcceptable()-是否接收就绪;  selectionKey.isConnectable()-是否连接就绪; selectionKey.isReadable()-是否读就绪;  selectionKey.isWritable()-是否写就绪;

Selector的select()方法阻塞到至少有一个通道在你注册的事件上就绪了。

Selector执行IO操作的步骤:

1)在Selector中注册Channel,注册的时候指定一个SelectionKey。

2)调用Selector.select()方法等待直到有一个通道在你注册事件上就绪了。

3)调用Selector.selectedKey()方法返回Selector已选择的键集,这个集合中就是第一步中注册Channel时返回的SelectionKey对象,而此时这个SelectionKey对象持有的Channel已经准备就绪。

4)这时可以通过SelectionKey的isAcceptable()、isConnectable()、isReadable()、isWritable()来进行判断第三步中的已经准备就绪的Channel是在哪个事件上准备就绪,而这个事件就是注册Channel时的事件。比如:isAcceptable方法对应的就是注册时的SelectionKey.OP_ACCEPT。

5)从selectionKey中取出Channel进行数据流的操作,操作完后移除该SelectionKey对象,一般使用Selectionkey的Iterator的remove事件进行移除。

6)操作完后继续注册Channel到selector的下一个事件,比如:ServerSocket的OP_ACCEPT的下一个事件是OP_READ,OP_READ之后是OP_WRITE。

7)注册新的状态之后再执行第2到第6步。

8)所以一般第2步到第6步是在一个while循环中执行的,在每一次执行完相应的操作后都要重新注册新的SelectionKey同时移除上一个已经处理完的SelectionKey,就这样完成了从等待链接到读取到写入再到等待链接等一系列循环。

3.java对象的序列化和反序列化

java序列化有两种方式:一种是实现Serializable接口,一种是实现Externalizable接口(需要实现writeExternal()和readExternal()方法,在序列化和反序列化的时候自动调用)。

如果实现Serializable接口也希望在序列化和反序列化的时候加入自己的方法,可以添加(不是覆盖)writeObject()和readObject()方法。

4.最后说一句

Java的NIO实现过于复杂,一般人真的不太好驾驭,建议直接使用Netty进行开发,省时省力,性能还好,就连Google都在用

相关文章

  • Java I/O相关

    I/O类的结构体系 I/O体系包含字节流、字符流、文件流和一个接口Serializable。字节流包含输入流Inp...

  • java BIO和NIO

    BIO: blocking I/O 。 BIO就是传统I/O,其相关的类和接口在 java.io 包下 BIO 是...

  • IO流之IO,NIO和AIO讲解

    1 IO,NIO,AIO 1.1 各个基本概念 Java I/O 的相关方法如下所述: 同步并阻塞 (I/O 方法...

  • 服务端 I/O 性能大比拼:Node、PHP、Java、Go

    摘要:本文首先简单介绍了 I/O 相关的基础概念,然后横向比较了 Node、PHP、Java、Go 的 I/O 性...

  • IO详解

    2.1 IO详解 本文将介绍Java语言中与I/O操作相关的内容,主要是流式I/O,关于NIO,我们之后会介绍。 ...

  • java day 17

    I/O java I/O读写基本类相关知识学习创建文件夹 创建文件 遍历文件夹下的文件 写入文件 读取文件

  • 线上学习资料汇总_新

    1. Java I/O 这些年一直记不住的 Java I/O 深入分析 Java I/O 的工作机制 NIO 入门...

  • Java-I/O学习(1)

    Java-I/O学习(1) Java IO是java中的相关API,主要目的为读数据与写数据(input 和 ou...

  • NIO.2-简介

    More New I/O Java 7 中的 More New I/O APIs,通过在 java.nio.cha...

  • Java & Groovy & Scala & Kotlin -

    Overview 文章介绍的 I/O 主要用于本地文件读写,不涉及网络 I/O。 Java 篇 Java 中的 I...

网友评论

      本文标题:Java I/O相关

      本文链接:https://www.haomeiwen.com/subject/muyglttx.html