Java NIO

1.前面介绍的IO当读取数据时,如果没有读取到数据或者数据源中没有数据,都会阻塞给线程,都是阻塞式的输入、输出。


2.面向流的输入输出系统一次只能处理一个字节,因此面向流的输入输出系统通常效率并不高。


3.从JDK1.4开始,java提供了一系列改进的输入输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),新增了许多用于处理输入
输出的类,这些类都被放在java.nio包及其子包下,并且对原java.io包中很多类都以NIO为基础进行了改写,新增了满足NIO的功能。


4.新IO和传统IO有相同的目的,都是用于进行输入输出,但新IO使用了不同的方式来处理输入输出,新IO采用内存映射文件的方式来处理输入
输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了(这种方式模拟了操作系统上面的虚拟内存的概念),
通过这种方式来进行输入输出比传统的输入输出要快的多。


5.Channel(通道)和Buffer(缓冲)是新IO中的两个核心对象,Channel是对传统的输入输出系统的模拟,在新IO系统中所有数据都需要
通过通道传输; map()方法可以直接将“一块数据”映射到内存中。如果说传统的输入输出系统是面向流的处理,则新的IO则是面向块的处理。


6.Buffer是一个抽象类,其最常用的子类有ByteBuffer和CharBuffer(除boolean外,其他基本数据类型都有对应的BUffer类)
这些Buffer类都没有提供构造器,通过使用static XxxBuffer allocate(int capacity)来创建一个容量为capacity的对象


7.在Buffer中有三个重要的概念:
容量(capacity):缓冲区的容量表示该Buffer的最大数据容量,即最多可以存储多少数据;缓冲区容量不可能为负值,创建后不能改变
界限(limit):第一个不应该被读出或者写入的缓冲区位置索引。也就是说,位于limit后的数据既不可被读,也不可被写。
位置(position):用于指明下一个可以被读出或者写入的缓冲区位置索引(类似于IO流中的记录指针)。


8.通过allocate方法创建的Buffer对象是普通的Buffer对象,ByteBuffer还提供了一个allocateDirect()方法来创建直接
Buffer。直接Buffer的创建成本比普通Buffer的创建成本高,但直接Buffer的读取效率更高。直接Buffer只使用于长生存期的
Buffer,而不适用于短生存期、一次用完就丢弃的Buffer,只有ByteBuffer提供了allocateDirect()方法。

9.Channel类似于传统的流对象,但与传统的流对象有两个主要的区别:

(1).Channel可以直接将指定文件的部分或全部直接映射成Buffer
(2).程序不能直接访问Channel中的数据,包括读取、写入都不行,Channel只能与Buffer进行交互

map()方法用于将Channel对应的部分或全部数据映射成ByteBuffer。
read()和write()方法用于从Buffer中读取或写入数据。

10.如果担心Channel对应文件过大,使用map()方法一次将文件所有内容映射到内存引起性能下降,也可以使用Channel和Buffer

传统的“用竹筒多次取水”的方式。

11.编码(Encoder)和解码(Decoder),通常而言,把明文的字符序列转换成计算机理解的二进制序列称为编码,把二进制字符序列
转换成普通人能看懂的明文字符串称为解码


12.如果多个运行的程序需要并发修改同一个文件时,程序之间需要某种机制来进行通信,使用文件锁可以有效阻止多个进程并发修改同一个文件
所以现在大部分操作系统都提供了文件锁功能。

lock()和tryLock()方法存在区别:当lock试图锁定某个文件时,如果无法得到文件锁,程序将一直阻塞,而tryLock()是尝试
锁定文件,它将直接返回而不是阻塞,如果获得了文件锁,该方法则返回该文件锁,否则将返回null。

直接使用lock()或tryLock()方法获取的文件锁是排他锁。

文件锁虽然可以用于控制并发访问,但是对于高并发访问的情形,还是推荐使用数据库来保存程序信息,而不是使用文件。

13.java7的NIO.2
(1).提供了全面的文件IO和文件系统访问支持
(2).基于异步Channel的IO
Path接口代表一个平台无关的平台路径

14.使用FileVisitor(文件访问器)遍历文件和目录;
在以前的java版本中,如果程序要遍历指定目录下的所有文件和子目录,则只能使用递归进行遍历,但这种方式不仅复杂,而且灵活性也不高。

15.使用WatchService监控文件变化

在以前的java版本中,如果程序需要监控文件的变化,则可以考虑启动一条后台线程,这条后台线程每隔一段时间去遍历一次指定目录的文件,
如果发现此次遍历结果与上次遍历结果不同,则认为文件发生了变化。但这种方式不仅十分繁琐,而且性能也不好。

该程序使用一个死循环重复获取E:盘根路径下文件变化,程序在<1>号代码处试图获取下一个WatchKey,如果没有发生就等待;
因此E:盘根路径下每次文件的变化都会被该程序监听到;

比如说:运行该程序,然后在E:盘下新建一个文件夹,再删除该文件,将会看到输出

16.访问文件属性

posted @ 2016-08-26 20:49  ﹍。GG╊棒°  阅读(123)  评论(0)    收藏  举报