前言

Channels和Buffers是JAVA NIO里面比较重要的两个概念,NIO正是基于Channels和Buffers进行数据操作,且数据总是从Channels读取到Buffers,或者从Buffers写入到Channels。

通道(Channel)

NIO中的通道与IO中的流类似,不过流是单向的,而通道是双向的。例如InputStream、OutputStream等都是单向的,一个流只能进行读数据或写数据;而FileChannel、SocketChannel等是双向的,既可以从中读数据,也可以写数据。

通道与流的区别如下:

  • 通道是双向的,可读可写,而流是单向的,只能读或只能写;
  • 通道中的数据是跟Buffer进行交互的,但在面向流的I/O中,数据是直接读/写到流中的;
  • NIO可以异步读写数据;

以FileChannel为例,如下:

FileChannel

FileChannel是文件写入/读取相关的通道;

产生FileChannel的方式:

  • 从FileOutputStream中获取;
  • 从RandomAccessFile中获取;
  • 从FileInputStream中获取;

下面举个例子,分别从FileOutputStream、RandomAccessFile、FileInputStream中获取文件通道,进行相关写入/读取操作;

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*; public class GetChannel {
private static final int BSIZE = 1024; public static void main(String[] args) throws Exception {
// 创建文件输出字节流
FileOutputStream fos = new FileOutputStream("data.txt");
//得到文件通道
FileChannel fc = fos.getChannel();
//往通道写入ByteBuffer
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
//关闭流
fos.close(); //随机访问文件
RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
//得到文件通道
fc = raf.getChannel();
//设置通道的文件位置 为末尾
fc.position(fc.size());
//往通道写入ByteBuffer
fc.write(ByteBuffer.wrap("Some more".getBytes()));
//关闭
raf.close(); //创建文件输入流
FileInputStream fs = new FileInputStream("data.txt");
//得到文件通道
fc = fs.getChannel();
//分配ByteBuffer空间大小
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
//从通道中读取ByteBuffer
fc.read(buff);
//调用此方法为一系列通道写入或相对获取 操作做好准备
buff.flip();
//从ByteBuffer从依次读取字节并打印
while (buff.hasRemaining()){
System.out.print((char) buff.get());
}
fs.close();
}
}

再举个文件复制的例子,有两种方式:

  • 打开一个FileChannel用于读,另一个用于写;
  • 直接调用transferTo或者transferFrom方法传输通道之间的数据;

如下代码示例:

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*; public class ChannelCopy {
private static final int BSIZE = 1024; public static void main(String[] args) throws Exception {
//获取文件输入输出字节流
FileInputStream fis = new FileInputStream("C:\\test.jpg");
FileOutputStream fos = new FileOutputStream("C:\\test_copy.jpg"); //从文件输入输出字节流中获取通道
FileChannel fci = fis.getChannel();
FileChannel fco = fos.getChannel();
//分配ByteBuffer空间大小
ByteBuffer buffer = ByteBuffer.allocate(BSIZE); //第一种种数据拷贝方式,直接往输入通道写数据
while (fci.read(buffer) != -1) {
//为写入操作做准备
buffer.flip();
//往输出通道写入buffer
fco.write(buffer);
//清空buffer,重置内部指针
buffer.clear();
} //第二种数据拷贝方式,利用transferTo或者transferFrom方式
FileOutputStream fos2 = new FileOutputStream("C:\\test_copy2.jpg");
FileChannel fco2 = fos.getChannel();
fci.transferTo(0, fci.size(), fco2); fis.close();
fos.close();
fos2.close();
}
}

缓冲区(Buffer)

buffer用于与通道进行交互,举个例子如下,这里以ByteBuffer为例;

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*; public class GetChannel {
private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { // 随机访问文件
RandomAccessFile raf = new RandomAccessFile("C:\\data.txt", "rw");
// 得到文件通道
FileChannel fc = raf.getChannel(); ByteBuffer bf = ByteBuffer.allocate(BSIZE); int bytesRead = fc.read(bf); // read into buffer.
while (bytesRead != -1) {
// 通过flip()方法将Buffer从写模式切换到读模式
bf.flip();
while (bf.hasRemaining()) {
// 每次读取一个字节
System.out.print((char) bf.get()); } // 清空缓存,准备往缓存写数据
bf.clear();
bytesRead = fc.read(bf);
} // 关闭
raf.close();
}
}

Buffer基本方法

  • flip方法:从buffer读数据之前调用,从写模式切换到读模式;
  • clear:往buffer写数据之前调用,全部清除;
  • compact:往buffer写数据之前调用,只清除已读取的数据,新写入的数据会添加到未读数据末尾;

Buffer基本属性

  • capacity:buffer空间大小;
  • position:读写数据时的指针,指向当前位置;
  • limit:读数据时,表示当前可读数据的大小;写数据时,即buffer大小=capacity;

Buffer的类型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Buffer中写数据

  • 从Channel写到Buffer,调用通道的read(Buffer buffer)方法
  • put()方法写到Buffer里,调用Buffer的put方法

Buffer中读取数据

  • 从Buffer读取数据到Channel,调用通道的write(Buffer buffer)方法
  • 使用get()方法从Buffer中读取数据,调用Buffer的get方法

参考:http://ifeve.com/java-nio-all/

JAVA NIO中的Channels和Buffers的更多相关文章

  1. Java NIO中核心组成和IO区别

    1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...

  2. java NIO中的buffer和channel

    缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...

  3. Java NIO中的Buffer 详解

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  4. Java NIO中的缓冲区Buffer(一)缓冲区基础

    什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...

  5. 转载Java NIO中的Files类的使用

    Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法. Files.exists() Files.exits()方法用来检查给定的Path在文件 ...

  6. java NIO中的Reactor相关知识汇总 (转)

    一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往 ...

  7. Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather

    什么是Scatter/Gather scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散): ...

  8. Java NIO中的通道Channel(一)通道基础

    什么是通道Channel 这个说实话挺难定义的,有点抽象,不过我们可以根据它的用途来理解: 通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件.套接字...),反之亦然: 通道是访问IO服务 ...

  9. JAVA NIO 中的 zerocopy 技术提高IO性能

    关于一篇更详细更好的介绍 ZeroCopy技术的文章,可参考:JAVA IO 以及 NIO 理解 这篇文章介绍了 zerocopy技术来提高Linux平台上的IO密集型的JAVA应用程序的性能. ze ...

随机推荐

  1. 慎用Assembly.LoadFile()和Assembly.LoadFrom()

    经测这俩方法会锁住文件,导致程序运行期间无法对load过的程序集文件进行更名/删除/覆盖等等操作,考虑用Assembly.Load()文件字节组替代: Assembly.Load(File.ReadA ...

  2. .NET vs2010中使用IrisSkin2.dll轻松实现winForm窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤! 网上很多朋友说在VS2010中不能使用IrisSkin2.dll,我这里提供一个取巧的办法. Iri ...

  3. jquery选择器(综合)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. Social Media POC KT Session

    地址: 1. http://c0048925.itcs.hp.com:8080/datamining/report/brandfocus.html Social Media POC是针对Social ...

  5. Enum 枚举小结 java **** 最爱那水货

    import java.util.HashMap; import java.util.Map; /** * 收单行 大写首字母 和对应的编码<br/> * * ABC 农业银行<br ...

  6. Selenium学习笔记之外部化相关测试数据---xml

    我们也可以用xml来定义一个信息更为丰富的UIMap.xml文件,比如,额外还添加控件所属的页,控件的类型,然后解析构建一个XMLParser类来读取相应的值. <?xml version=&q ...

  7. DDD为何叫好不叫座?兼论DCI与业务分析的方法论

    今天,仔细阅读了园子里面的一个朋友写的<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>(http://www.cnblogs.com/ ...

  8. Codrops 教程:实现内容倾斜的 3D 幻灯片效果

    今天给大家分享的优秀教程来自 Codrops 网站,实现一个内容倾斜的 3D 幻灯片效果.我们平常见到的都是那种水平或者垂直滚动的效果,这个倾斜的内容滑动效果相信会让你眼前一亮.因为使用了 CSS 3 ...

  9. mysql win源码比较大 不需要的文件删除 记录下来

    mysql-5.6.25-win32.zip 从官方下载下来的大小为 343MB,太大了可以删除掉的地方记录一下 docs :全部删除. sql-bench:全部删除. mysql-test :全部删 ...

  10. Web安全之CSRF攻击

    CSRF是什么? CSRF(Cross Site Request Forgery),中文是跨站点请求伪造.CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任, ...