设为首页 加入收藏

TOP

走进Java NIO的世界(一)
2015-12-01 14:11:41 来源: 作者: 【 】 浏览:8
Tags:走进 Java NIO 世界

Java NIO 简介


Java NIO,即Java New IO,是Java IO的2.0版本,since from JDK1.4。JDK1.4以前提供的都是传统的IO,即我们经常使用的InputStream/OutputStream/Reader/Writer等。对于传统IO,我们可以利用流的装饰功能,使其具有Buffer功能,本质上是利用byte[]完成的。而Java NIO单独把Buffer的功能抽取出来,而且还提供了很多特性,下面我们一起来看看吧~


Buffer家族


看下java.nio.Buffer的子类:


走进Java NIO的世界


对于基本数据类型,基本上都有与之对应的Buffer类,而ByteBuffer最常用,ByteBuffer下面又有2个特殊的子类。


ByteBuffer


先来一段代码,有点感性认识吧:


public static void main(String[] args) {
? ? //分配Buffer缓冲区大小? 其本质是指定byte[]大小
? ? ByteBuffer buffer = ByteBuffer.allocate(10);
? ? printBuffer(buffer);
? ? buffer.put((byte)1);
? ? printBuffer(buffer);
? ? buffer.flip();
? ? printBuffer(buffer);
}
public static void printBuffer(Buffer buffer){
? ? System.out.println("--------");
? ? System.out.println("position : " + buffer.position());
? ? System.out.println("limit : " + buffer.limit());
? ? System.out.println("capacity : " + buffer.capacity());
? ? System.out.println("--------");
}


既然要使用ByteBuffer,必然要知道如何创建它!常见的创建ByteBuffer的方式有如下几种:


分配堆内存的方式


public static ByteBuffer allocate(int capacity) {
? ? if (capacity < 0)
? ? ? ? throw new IllegalArgumentException();
? ? return new HeapByteBuffer(capacity, capacity);
}


分配直接内存,即C HEAP的方式


? public static ByteBuffer allocateDirect(int capacity) {


? ? ? ? return new DirectByteBuffer(capacity);
? }


需要注意的是,DirectByteBuffer是MappedByteBuffer的子类!


直接包装byte[]形成ByteBuffer


public static ByteBuffer wrap(byte[] array,
? ? int offset, int length){
? ? ? ? try {
? ? ? ? ? ? return new HeapByteBuffer(array, offset, length);
? ? ? ? } catch (IllegalArgumentException x) {
? ? ? ? ? ? throw new IndexOutOfBoundsException();
? ? ? ? }
? ? }


由于ByteBuffer是atstract class,因此我们使用的都是它的2个具体子类:HeapByteBuffer/MappedByteBuffer。


我们可以跟踪下HeapByteBuffer/DirectByteBuffer的构造方法,发现它们其实就做了一件事:


初始化byte[]以及一些属性,比如mark,position,limit,capacity。


position vs limit vs capacity


Java NIO中ByteBuffer除了有byte[]之外,还提供了一些属性,这样相比传统IO,操作更加灵活方便。


首先来说,capacity是byte[]的容量大小,一般是初始化好后,就不会在变化了的,而position,limit这2个属性,会随着对缓冲区的read/write操作而发生变化。


position:下一个应该读取的位置


limit:在byte[]中有效读取位置的最大值


下面,我们来做一个例子具体说明:利用ByteBuffer来拷贝文件


public static void closeStream(Closeable... closeable){
? ? for(Closeable c : closeable){
? ? ? ? if(c != null){
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? c.close();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
}


public static void main(String[] args) throws IOException {
? ?
? ? FileInputStream srcFile = new FileInputStream("E:\\tmp\\Shell学习笔记.pdf");
? ? FileOutputStream? destFile = new FileOutputStream("E:\\tmp\\Shell学习笔记COPY.pdf");
? ?
? ? ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
? ?
? ? 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则更加简单

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇关于EditText的一点深入的了解 下一篇Python面试必须要看的15个问题

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: