Java I/O相关

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都在用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容

  • Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java I...
    JackChen1024阅读 7,555评论 1 143
  • 简介 Java NIO 是由 Java 1.4 引进的异步 IO.Java NIO 由以下几个核心部分组成: Ch...
    永顺阅读 1,791评论 0 15
  • (转载说明:本文非原创,转载自http://ifeve.com/java-nio-all/) Java NIO: ...
    数独题阅读 805评论 0 3
  • (转载说明:本文非原创,转载自http://ifeve.com/java-nio-all/) Java NIO: ...
    柳岸阅读 818评论 0 3
  • 这两天了解了一下关于NIO方面的知识,网上关于这一块的介绍只是介绍了一下基本用法,没有系统的解释NIO与阻塞、非阻...
    Ruheng阅读 7,124评论 5 48