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[]是我们要存储读取到用户空间的缓冲区 ...
随机推荐
- Activity讲解
Activity Activity 是 Android 应用的重要组成单元之一(另外三个是 Service.BroadcastReceiver 和 ContentProvider),而 Activit ...
- Unity20172.0 Android平台打包
Android SDK及Jdk百度网盘下载链接:https://pan.baidu.com/s/1dFbEmdz 密码:pt7b Unity20172.0 Android平台打包 简介说明: 第一步: ...
- C#.Net与MATLAB集成
在数学分析工具方面,MATLAB无疑是佼佼者,除了作为软件工具外,MATLAB的自定义编程语言以及混合编程的支持,使其可以与Python.R之类数学分析语言媲美.尤其是在一些传统领域的研究,由于其研究 ...
- codeforces 893C Rumor 前向星+dfs
893C Rumor 思路: 前向星+DFS 代码: #include <bits/stdc++.h> using namespace std; #define _for(i,a,b) f ...
- 洛谷 P3379 【模板】最近公共祖先(LCA)Tarjan离线
题目链接:LCA tarjan离线 这道题目WA无数发,最后还是参考了大神的blog 谁会想到因为一个输入外挂WA呢 大概是我的挂是假挂吧...orz(其实加上外挂,速度提升很多) 用链式前向星保存边 ...
- CCF-201412-2-Z字形扫描
问题描述 试题编号: 201412-2 试题名称: Z字形扫描 时间限制: 2.0s 内存限制: 256.0MB 问题描述: 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zi ...
- Springboot读取配置文件及自定义配置文件
1.创建maven工程,在pom文件中添加依赖 <parent> <groupId>org.springframework.boot</groupId> <a ...
- .NET版支付宝商户会员卡接入
最近公司计划对接支付宝会员卡功能,而任务恰巧由领导安排给我这边,小弟之前也未做过支付宝接口,研究了三天,终于将支付宝会员卡API接口大体上调通了,现将其整理下,以供参考. 蚂蚁金服开发平台-商户会员卡 ...
- JavaWeb学习总结(二)——Tomcat服务器学习和使用(一)(转)
转载自 http://www.cnblogs.com/xdp-gacl/p/3734395.html 一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的serve ...
- 剑指Offer_6_从尾到头打印链表
题目描述 输入应该链表的头节点 , 从尾到头反过来打印出每个节点的值.链表定义如下 : typedef struct ListNode { int m_nKey ; ListNode * ...