Java NIO (三) 通道(Channel)
通道(Channel):由 java.nio.channels 包定义的,Channel 表示 IO 源与目标打开的连接。Channel 类似于传统的“流”,只不过 Channel本身不能直接访问数据,Channel 只能与Buffer 进行交互。
Channel的顶层接口:
public interface Channel extends Closeable { public boolean isOpen(); public void close() throws IOException; }
其中只包含最基本的两个方法,如下图是从《Java NIO》截取的Channel继承树。
Channel可分为可读和可写,实现了对应的可读可写的Channel接口或者抽象Channel类,就可以读写兼并。
Java 为 Channel 接口提供的最主要实现类如下:
FileChannel:用于读取、写入、映射和操作文件的通道。
DatagramChannel:通过 UDP 读写网络中的数据通道。
SocketChannel:通过 TCP 读写网络中的数据。
ServerSocketChannel:可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel。
以上Channel都实现或者继承了相应的Channel读写接口或者读写抽象类,所以都是可读写的。但是因为FileChannel可以根据FileInputStream或者FileOutputStream获取,所以当根据以上类获取的FileChennel进行读或者写的时候会抛出异常。
获取Channel对象:
1. FileChannel对象的获取:
@Test
public void test() throws IOException{
//1. 使用FileInputStream获取FileChannel
FileInputStream fis = new FileInputStream("d:\\1.txt");
FileChannel fChannel = fis.getChannel();
//2. 使用FileOutputStream获取FileChannel
FileInputStream ois = new FileInputStream("d:\\1.txt");
FileChannel fChannel1 = ois.getChannel();
//3, 使用RandomAccessFile对象获取
RandomAccessFile raf = new RandomAccessFile("d:\\1.txt", "rw");
FileChannel fChannel2 = raf.getChannel();
//4. FileChannel的open方法打开
FileChannel fChannel3 = FileChannel.open(Paths.get("d:\\1.txt"), StandardOpenOption.READ,StandardOpenOption.WRITE);
}
2. 其他三个网络Channel的获取方式:
@Test
public void test2() throws IOException{
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
ServerSocketChannel ssChannel = ServerSocketChannel.open();
DatagramChannel datagramChannel = DatagramChannel.open();
}
Channel的读写:
1. 从Channel中读取数据到buffer
public abstract int read(ByteBuffer dst) throws IOException;
public abstract long read(ByteBuffer[] dsts, int offset, int length)throws IOException;
public final long read(ByteBuffer[] dsts) throws IOException {
return read(dsts, 0, dsts.length);
}
2. 将buffer中的数据写入Channel
public abstract int write(ByteBuffer src) throws IOException;
public abstract long write(ByteBuffer[] srcs, int offset, int length)throws IOException;
public final long write(ByteBuffer[] srcs) throws IOException {
return write(srcs, 0, srcs.length);
}
3. 如下一段文件读写的代码
public void test3() {
FileInputStream fis = null;
FileChannel inputChannel = null;
FileOutputStream fos = null;
FileChannel outputChannel = null;
try {
fis = new FileInputStream("d:\\1.txt");
inputChannel = fis.getChannel(); fos = new FileOutputStream("d:\\1.bak.txt");
outputChannel = fos.getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024);
int len = -1;
while ((len = inputChannel.read(buf)) != -1) {
buf.flip();
outputChannel.write(buf);
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputChannel != null) {
try {
outputChannel.close();
} catch (Exception e2) {
}
}
if (outputChannel != null) {
try {
outputChannel.close();
} catch (Exception e2) {
}
}
if (inputChannel != null) {
try {
inputChannel.close();
} catch (Exception e2) {
}
}
if (fos != null) {
try {
fos.close();
} catch (Exception e2) {
}
}
if (fis != null) {
try {
fis.close(); } catch (Exception e2) {
}
} } }
Channel的transferFrom和transferTo,看如下代码(为了看着简单异常直接抛出去):
public void test4() throws IOException {
FileInputStream fis = new FileInputStream("d:\\1.txt");
FileChannel inputChannel = fis.getChannel();
FileOutputStream fos = new FileOutputStream("d:\\1.bak.txt");
FileChannel outputChannel = fos.getChannel(); // 直接从通道中读,在内存中分配空间,在物理内存中直接操作
// inputChannel.transferTo(0,inputChannel.size() , outputChannel);
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
}
分散(Scatter)和聚集(Gather)
1. 分散是将一个Channel中的数据写到多个顺序的buffer中,一般是传进一个buffer数组中,Channel中的数据依次写入buffer数组中的buffer当中。
2. 聚集是将多个buffer中的数据写入同一个buffer中,一般操作是一个buffer数组。
代码如下:
@Test
public void test5() throws IOException {
FileInputStream fis = new FileInputStream("d:\\1.txt");
FileChannel inputChannel = fis.getChannel();
FileOutputStream fos = new FileOutputStream("d:\\1.bak.txt");
FileChannel outputChannel = fos.getChannel(); ByteBuffer buf1 = ByteBuffer.allocate(1024);
ByteBuffer buf2 = ByteBuffer.allocate(64);
ByteBuffer buf3 = ByteBuffer.allocate(32);
ByteBuffer[] bufs = { buf1, buf2, buf3 }; while (inputChannel.read(bufs) != -1) {
// 分散读取(Scattering Reads)
inputChannel.read(bufs); for (ByteBuffer buf : bufs) {
buf.flip();
}
// 聚集写入(Gathering Writes)
outputChannel.write(bufs); for (ByteBuffer buf : bufs) {
buf.clear();
}
}
}
Channel暂时想到这么多东西,后续有想到的再补充,开始写博客欢迎批评指正。
参看资料: 《Java NIO 中文版》
Java NIO (三) 通道(Channel)的更多相关文章
- Java NIO之通道Channel
channel与流的区别: 流基于字节,且读写为单向的. 通道基于快Buffer,可以异步读写.除了FileChannel之外都是双向的. channel的主要实现: FileChannel Data ...
- Java NIO学习笔记---Channel
Java NIO 的核心组成部分: 1.Channels 2.Buffers 3.Selectors 我们首先来学习Channels(java.nio.channels): 通道 1)通道基础 通道( ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
- 5. 彤哥说netty系列之Java NIO核心组件之Channel
你好,我是彤哥,本篇是netty系列的第五篇. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Java NIO的核心组件之一--Channel. 思维转变 首先, ...
- JAVA NIO Socket通道
DatagramChannel和SocketChannel都实现定义读写功能,ServerSocketChannel不实现,只负责监听传入的连接,并建立新的SocketChannel,本身不传输数 ...
- Java NIO之通道
一.前言 前面学习了缓冲区的相关知识点,接下来学习通道. 二.通道 2.1 层次结构图 对于通道的类层次结构如下图所示. 其中,Channel是所有类的父类,其定义了通道的基本操作.从 Channel ...
- 【NIO】Java NIO之通道
一.前言 前面学习了缓冲区的相关知识点,接下来学习通道. 二.通道 2.1 层次结构图 对于通道的类层次结构如下图所示. 其中,Channel是所有类的父类,其定义了通道的基本操作.从 Channel ...
- Java NIO:通道
最近打算把Java网络编程相关的知识深入一下(IO.NIO.Socket编程.Netty) Java NIO主要需要理解缓冲区.通道.选择器三个核心概念,作为对Java I/O的补充, 以提升大批量数 ...
- Java NIO 之 Socket Channel
在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件.Socket或其他设备.简而言之,指代了一种与IO操作对象间的连接关系. 按照Channel ...
- Java IO和Java NIO 和通道 在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
随机推荐
- HBase表预分区与压缩
1.建立HBase预分区表.sql语句如下: create 'buyer_calllogs_info_ts', 'record', {SPLITS_FILE => 'hbase_calllogs ...
- NYOJ 119 士兵杀敌(三) RMQ ST
NYOJ 119 士兵杀敌(三) RMQ ST 题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=119 思路: ST在线 预处理O(nlog ...
- 深入解析Java垃圾回收机制
引入垃圾回收 哪些内存需要回收? 引用计数法 可达性分析 如何回收 Marking 标记 Normal Deletion 清除 Deletion with Compacting 压缩 为什么需要分代收 ...
- Postgres是如何管理空值的
创建表test,y字段插入null. test=# create table test(x bigint,y bigint,z text); CREATE TABLE test=# insert in ...
- Android异步消息机制
Android中的异步消息机制分为四个部分:Message.Handler.MessageQueue和Looper. 其中,Message是线程之间传递的消息,其what.arg1.arg2字段可以携 ...
- js函数的作用域与this指向
函数的作用域与this指向是js中很重要的一部分,理清这点东西需要个逻辑,看看我的逻辑怎么样... 下面是个提纲,可以直接挑你感兴趣的条目阅读. 函数的定义方式:直接定义(window下,内部定义), ...
- oracle用户被锁定
sqlplus sys/password@localhost:1521/cmsx as sysdba SQL*Plus: Release 11.2.0.1.0 Production on 星期一 7月 ...
- caffe在windows编译project及执行mnist数据集測试
caffe在windows上的配置和编译能够參考例如以下的博客: http://blog.csdn.net/joshua_1988/article/details/45036993 http://bl ...
- ORA-16032: parameter LOG_ARCHIVE_DEST_3 destination string cannot be translated问题处理过程
1,现象是oracle启动报错例如以下: SQL> startup ORA-16032: parameter LOG_ARCHIVE_DEST_3 destination string cann ...
- Ansible@一个高效的配置管理工具--Ansible configure management--翻译(一)
未经书面许可,请勿转载 --- Ansible is the simplest way to automate apps and IT infrastructure 这是Ansible官方站 ...