FileChannel in = srcFile.getChannel(); FileChannel out = destFile.getChannel();
while(in.read(byteBuffer) != -1){ byteBuffer.flip(); out.write(byteBuffer); byteBuffer.clear(); } closeStream(srcFile,destFile); }其实,通过上面的代码,我们已经揭示了Java NIO的3个核心概念中的2个:缓冲区与通道以前,对于传统IO,我们面对的是流,操作的是一个个字节,而NIO,我们面对的是缓冲区,操作的将是一个个块。具体来说,是这样的:读取输入,比如读取文件,那么应该通过FileInputStream/RandomAccessFile进行获取通道;创建缓冲区buffer;然后调用通道的read操作,将数据读入buffer。写操作,则相反。上面代码中,调用了buffer的2个重要方法:flip()/clear(),他们是干嘛的呢?直接看源码: public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }flip并没有做什么,只是将limit的位置设置为position,而position的位置回到0 public final Buffer clear() { position = 0; limit = capacity; mark = -1; return this; }clear则更加简单,回到最初的状态!为什么要调用他们来改变limit/positon呢?要知道,如果channel.read(buffer),这个操作,是要改变position的;如果我们继续otherchannel.write(buffer),那么将写入的是未知数据。最好的方式,是将position现在所处的位置交给limit,而position置为0,这样就到达了将缓冲区的内容重新读出!而调用clear的目的,就更加单纯,就是希望在read(buffer)的时候从0开始!mark是来做什么的?在buffer中,mark默认是被置为-1的。我们先来看看与mark有直接关系的2个方法: public final Buffer mark() { mark = position; return this; } public final Buffer reset() { int m = mark; if (m < 0) throw new InvalidMarkException(); position = m; return this; }通过mark()我们利用mark记住了position,而通过reset()我们将position的值还原到mark。那么事实就清楚了,我们可以先调用mark()记住当前POSITION的位置,然后我们去做其他的一些事情,最后通过reset()在找回POSITION的位置开始下一步!allocateDirectallocateDirect方式创建的是一个DirectByteBuffer,直接内存,这是用来做什么的呢?我们可以先来看看常规的IO操作流程:很显然,JVM只是普通的用户进程,能够和IO设备打交道的是KERNEL空间,JVM需要从KERNEL拷进INPUT DATA,拷出OUTPUT DATA到KERNEL。当然,频繁的拷进拷出操作是费时的。而DirectBuffer将跳过JVM拷进拷出这一层。MappedByteBuffer:内存映射IO我们经常是在内存中分配一段空间,操作完毕后,写入磁盘;那么能不能在磁盘上直接分配一段空间,供我们进行IO操作呢?MappedByteBuffer就是这样的,它会在磁盘上分配一段缓冲区,对缓存区的操作就是对磁盘的操作!来看看“高性能”的拷贝文件方式:利用MappedByteBufferpublic static void main(String[] args) throws IOException { //FileInputStream fis = new FileInputStream("E:\tmp\Shell学习笔记.pdf"); //FileOutputStream fos = new FileOutputStream("E:\tmp\Shell学习笔记COPY.pdf"); RandomAccessFile fis = new RandomAccessFile("E:\tmp\Shell学习笔记.pdf","r"); RandomAccessFile fos = new RandomAccessFile("E:\tmp\Shell学习笔记COPY.pdf","rw"); FileChannel in = fis.getChannel(); FileChannel out = fos.getChannel(); long size = in.size(); ByteBuffer buffer = out.map(MapMode.READ_WRITE, 0, size); in.read(buffer); closeStream(fis,fos); }可以看得出,先利用FileChannel的map方法获取一个可读、可写的position=0,大小为size的MappedByteBuffer,对这个buffer的操作就将直接反映到磁盘上!【注意到,利用FileInputStream获取到的CHANNEL是只读的,利用FileOutputStream获取到的CHANNEL是只写的,而map获取BUFFER需要读写权限,因此要利用RandromAccessFile来进行读写设置!】到这里,JAVA NIO就介绍了一部分内容了,我也从知道有NIO,到开始实践NIO了,HAPPY.....本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-11/125439.htm