前言

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. 聊一下C#开发者如何过渡到JAVA 开发者

    由于工作需要,最近也开始倒腾Java了.NET的话,从2012年测试版开始玩的,那个时候VB6比较熟悉,还天真的以为VB.NET以后会很火, 事实证明,也只是一厢情愿,有C#了,要VB.NET干什么? ...

  2. .NET 中获取调用方法名

    在写记录日志功能时,需要记录日志调用方所在的模块名.命名空间名.类名以及方法名,想到使用的是反射(涉及到反射请注意性能),但具体是哪一块儿还不了解,于是搜索,整理如下: 需要添加相应的命名空间: us ...

  3. Software Development Engineer - Database Services

    http://stackoverflow.com/jobs/116486/software-development-engineer-database-services-amazon?med=clc& ...

  4. 最小生成二叉树-prim算法

    1.prim算法:一种计算生成最小生成树的方法,它的每一步都会为一棵生长中的树添加一条边. 2.时间复杂度:

  5. mysql和oracle jdbc连接

    加载驱动. Class.forName("oracle.jdbc.driver.OracleDriver"); 1 创建连接. Connection con = DriverMan ...

  6. 让我们来讲讲,SCRUM和AGILE(资料来源:https://www.youtube.com/ 文中有代理参数配置)

    本期我们讨论的主题是项目管理 以前,一直以为“ Write the code, Change the world ”.但实质上,我们就一写代码的.如果我们能上升到项目管理的角度来实行Project M ...

  7. [Android] 建立与使用Library

    [Android] 建立与使用Library 前言 使用Eclipse开发Android项目时,开发人员可以将可重用的程序代码,封装为Library来提供其他开发人员使用.本篇文章介绍如何将可重用的程 ...

  8. 分享22款响应式的 jQuery 图片滑块插件

    响应式(Responsive)设计的目标是要让产品界面能够响应用户的行为,根据不同终端设备自动调整尺寸,带给用户良好的使用体验.这篇文章收集了22款优秀的响应式 jQuery 幻灯片插件,它们能够帮助 ...

  9. Quill – 可以灵活自定义的开源的富文本编辑器

    Quill 的建立是为了解决现有的所见即所得(WYSIWYG)的编辑器本身就是所见即所得(指不能再扩张)的问题.如果编辑器不正是你想要的方式,这是很难或不可能对其进行自定义以满足您的需求. Quill ...

  10. CSS3 使用自定义字体

    CSS3 @font-face 规则 在 CSS3 之前,web 设计师必须使用已在用户计算机上安装好的字体.通过 CSS3,web 设计师可以使用他们喜欢的任意字体.当您您找到或购买到希望使用的字体 ...