3.通道 Channel
一、通道(Channel):由java.nio.channels包定义的 。Channel 表示 IO 源与目标打开的连接。
Channel 类似于传统的 ‘流’。只不过 Channel 本身不能直接访问数据,Channel只能与Buffer进行交互
二、 /*通道的主要实现类*/
Java 为 Channel 接口提供的 最主要实现类如下:
FileChannel:用于读取、写入、映射和操作文件的通道
SocketChannel:通过TCP 读写网络中的数据
ServerSocketChannel:可以监听新进来的TCP连接,对每一个新进来的连接都会创建一个 SocketChannel
三、 /*如何获取通道*/
获取通道
* 1.Java针对 支持通道的类提供了 getChannel()方法
* 本地IO:
* FileInputStream/FileOutputStream
* RandomAccessFile
* 网络IO:
* Socket
* ServerSocket
* DatagramSocket
2.在 JDK1.7 中 的 NIO.2 针对各个通道提供了静态方法 open()
3.在 JDK1.7 中 的 NIO.2 的 File 工具类的newByteChannel()
利用通道进行数据传输

四、 /*通道之间的数据传输*/
transferForm() 将数据从源通道 传输到其他 Channel中
transferTo() 其他 Channel 从 原通道中 获取数据
五、 /*分散(Scatter) 与 聚集(Gather)*/
分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区
聚集写入(Gathering Writes):将多个缓冲区中的 数据 聚集到通道中
六、 /*字符集:Charset*/
编码:字符串 -> 字节数组
解码: 字节数组 -> 字符串
/*
* 一、通道(Channel):用于源节点 与目标节点的连接 ,在java nio 中 负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输
*
* 二、通道的主要实现类
* java.nio.channels.Channel 接口
* |--FileChannel
* |--SocketChannel
* |--ServerSocketChannel
* |--DatagramChannel
*
* 三、获取通道
* 1.Java针对 支持通道的类提供了 getChannel()方法
* 本地IO:
* FileInputStream/FileOutputStream
* RandomAccessFile
*
* 网络IO:
* Socket
* ServerSocket
* DatagramSocket
*
* 2.在 JDK1.7 中 的 NIO.2 针对各个通道提供了静态方法 open()
*
* 3.在 JDK1.7 中 的 NIO.2 的 File 工具类的newByteChannel()
*
* 四、通道之间的数据传输
* transferForm()
* transferTo()
*
* 五、分散(Scatter) 与 聚集(Gather)
* 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区
* 聚集写入(Gathering Writes):将多个缓冲区中的 数据 聚集到通道中
*
* 六、字符集:Charset
* 编码:字符串 -> 字节数组
* 解码: 字节数组 -> 字符串
*
* */
public class TestChannel { //使用指定字符集 进行编码 和 解码
@Test
public void test6() throws IOException {
//1.选择字符集
Charset charset1 = Charset.forName("GBK"); //2.获取编码器
CharsetEncoder encoder = charset1.newEncoder(); //3.获取解码器
CharsetDecoder decoder = charset1.newDecoder(); //4.创建字符串缓冲区,放入需要编码的字符串
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("迅雷影音"); //5.对字符串进行编码 (编码:字符串 -> 字节数组)
charBuffer.flip(); //操作字符串缓冲区,解码字符串之前 需要 flip 一下
ByteBuffer byteBuffer = encoder.encode(charBuffer); // byteBuffer 此时 是 初始状态,即position 是0
//调用 这个 for ,每 get 一次,position + 1
//这样才能 在 flip 之后, 解码 需要操作的数据
for(int i = 0;i<8;i++) {
System.out.println(byteBuffer.position());
System.out.println(byteBuffer.get());
} //6.对字节数组进行解码 (解码: 字节数组 -> 字符串)
byteBuffer.flip(); //操作字节缓冲区,解码字节数组之前 需要 flip 一下
CharBuffer charBuffer2 = decoder.decode(byteBuffer); //打印解码后的数据
System.out.println(charBuffer2.toString());
} //5.显示所有的字符集
@Test
public void test5() {
Map<String,Charset> map = Charset.availableCharsets();
Set<Entry<String, Charset>> set = map.entrySet(); for(Entry<String, Charset> entry:set) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
} //4.分散和 聚集 (多个缓冲区)
@Test
public void test4() throws IOException {
// "rw" 是指 具有read 和 write 的 权限
RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
//1.获取通道
FileChannel channel1 = raf.getChannel(); //2.分配指定大小的缓冲区 (多个)
ByteBuffer buf1 = ByteBuffer.allocate(100);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
ByteBuffer[] bufs = {buf1,buf2}; //4.聚集写入
RandomAccessFile raf2 = new RandomAccessFile("2.txt","rw");
FileChannel channel2 = raf2.getChannel(); //3.分散读取
while(channel1.read(bufs)!= -1) {
for(ByteBuffer buf:bufs) {
buf.flip();
}
//4.聚集写入
channel2.write(bufs); System.out.println("-----------------缓冲区1---------------");
System.out.println(new String(bufs[0].array(),0,bufs[0].limit()) );
System.out.println("-----------------缓冲区1---------------"); System.out.println("-----------------缓冲区2---------------");
System.out.println(new String(bufs[1].array(),0,bufs[1].limit()));
System.out.println("-----------------缓冲区2---------------"); for(ByteBuffer buf:bufs) {
buf.clear();
} } } //3.通道之间的数据传输
@Test
public void test3() throws Exception {
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE); //直接使用transferTo 或者 transferFrom 完成通道之间的数据传输
inChannel.transferTo(0, inChannel.size(), outChannel);
outChannel.transferFrom(inChannel, 0, inChannel.size()); inChannel.close();
outChannel.close();
} //2.使用直接缓冲区完成文件的复制(内存映射文件)(这种方式效率更高)
//会出现的问题 :文件传输已经完成,但是程序仍然没有结束,因为 java 虚拟机无法及时 对 内存映射文件进行 进行释放,必须要等指向映射文件的那个变量被回收
@Test
public void test2() { long start = System.currentTimeMillis(); FileChannel inChannel = null;
FileChannel outChannel = null;
MappedByteBuffer inMapperBuf = null;
MappedByteBuffer outMapperBuf = null; try {
//使用 FileChannel 的 open方法 (可以不用创建流就可以得到通道)
inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE); //内存映射文件 (也是一个 缓冲区 ,继承自 ByteBuffer,直接缓冲区也只能使用 ByteBuffer)
inMapperBuf = inChannel.map(MapMode.READ_ONLY,0 , inChannel.size());
outMapperBuf = outChannel.map(MapMode.READ_WRITE,0 , inChannel.size()); } catch (IOException e) {
e.printStackTrace();
} //直接对缓冲区进行数据读写操作
byte[] bytes = new byte[inMapperBuf.limit()];
inMapperBuf.get(bytes);
outMapperBuf.put(bytes); try {
if(inChannel != null) {
inChannel.close();
}
if(outChannel != null) {
outChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
} long end = System.currentTimeMillis();
System.out.println("花费:" + (end-start)); } //1.利用通道完成文件的复制
@Test
public void test1() {
long start = System.currentTimeMillis(); FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("1.jpg");
fos = new FileOutputStream("2.jpg");
} catch (FileNotFoundException e) {
e.printStackTrace();
} //1.获取流对应的 通道
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel(); //2.分配指定大小的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024); //3.将通道中的数据存入缓存区
try {
//read 方法,从Channel 中读取数据到 ByteBuffer (即往 缓冲区中 put 数据),所以不用 flip
while(inChannel.read(buffer) != -1) {
buffer.flip(); //切换到读取数据模式 //4.将缓存区中的数据写入通道中 (需要get 出 缓冲区中的 数据 ,所以需要 flip)
outChannel.write(buffer);
buffer.clear(); //清空缓冲区,使其继续循环
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(inChannel != null) {
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outChannel != null) {
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} long end = System.currentTimeMillis();
System.out.println("花费:" + (end-start));
} }
3.通道 Channel的更多相关文章
- nio再学习之通道channel
通道(Channel):用于在数据传输过程中,进行输入输出的通道,其与(流)Stream不一样,流是单向的,在BIO中我们分为输入流,输出流,但是在通道中其又具有读的功能也具有写的功能或者两者同时进行 ...
- Java NIO中的通道Channel(一)通道基础
什么是通道Channel 这个说实话挺难定义的,有点抽象,不过我们可以根据它的用途来理解: 通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件.套接字...),反之亦然: 通道是访问IO服务 ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
- 理解CNN中的通道 channel
在深度学习的算法学习中,都会提到 channels 这个概念.在一般的深度学习框架的 conv2d 中,如 tensorflow .mxnet ,channels 都是必填的一个参数. channel ...
- go中的数据结构通道-channel
1. channel的使用 很多文章介绍channel的时候都和并发揉在一起,这里我想把它当做一种数据结构来单独介绍它的实现原理. channel,通道.golang中用于数据传递的一种数据结构.是g ...
- 详解 通道 (Channel 接口)
在本篇博文中,本人主要讲解NIO 的两个核心点 -- 缓冲区(Buffer) 和 通道 (Channel)之一的 缓冲区(Buffer), 有关NIO流的其他知识点请观看本人博文<详解 NIO流 ...
- Java NIO之通道Channel
channel与流的区别: 流基于字节,且读写为单向的. 通道基于快Buffer,可以异步读写.除了FileChannel之外都是双向的. channel的主要实现: FileChannel Data ...
- go实例之轻量级线程goroutine、通道channel与select
1.goroutine线程 goroutine是一个轻量级的执行线程.假设有一个函数调用f(s),要在goroutine中调用此函数,请使用go f(s). 这个新的goroutine将与调用同时执行 ...
- Java-NIO(四):通道(Channel)的原理与获取
通道(Channel): 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Chann ...
- Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather
什么是Scatter/Gather scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散): ...
随机推荐
- Kafka Connect REST Interface
Since Kafka Connect is intended to be run as a service, it also supports a REST API for managing con ...
- springboot拦截json后缀的请求,返回json数据
需求:请求list.json返回以下数据 { "jsonResult": { "code": 200, "message": "查 ...
- iOS-MPMoviePlayerController视频播放
视频MPMoviePlayerController 在iOS中播放视频可以使用MediaPlayer.framework种的MPMoviePlayerController类来完成,它支持本地 视频和网 ...
- url请求特殊字符转换
一.问题阐述 用URL传参数的时候,用&符号连接,如果某一个参数中含"#$ ^ & * + ="这些符号的时候,在另一个页面getParameter就会取不到传过来 ...
- eclipse 解决POM文件错误:org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration)
解决方案: 更新eclipse中的maven插件 1.1 Help -> Install New Software -> Add 1.2 Location中输入 http://repo1. ...
- 入行IT的选择决定了日后走的路的长度和领域的深度
前段时间和发小聊天时,他说了一句话我觉得很值得思考,送给大家:机遇大于努力,选择大于机遇. 一年前我毅然辞去了之前的工作,只身来到北京,正式成为了北漂的一员.对于我们现在的大环境下,其实北漂已经和以前 ...
- 《Hadoop》大数据技术开发实战学习笔记(二)
搭建Hadoop 2.x分布式集群 1.Hadoop集群角色分配 2.上传Hadoop并解压 在centos01中,将安装文件上传到/opt/softwares/目录,然后解压安装文件到/opt/mo ...
- 删除Excel表格中一堆英文中的汉字
昨天需要处理一个Excel文件,删除一堆英文里的汉字,开始搜了下方法,没找到,然后手动一个多小时,弄了一半吧也就,结果电脑卡了,忘了保存,就白做了...不知道为啥这次没有自动保存,所以,重要的事说三遍 ...
- 转 Linux平台卸载MySQL总结
如何在Linux下卸载MySQL数据库呢? 下面总结.整理了一下Linux平台下卸载MySQL的方法. MySQL的安装主要有三种方式:二进制包安装(Using Generic Binaries).R ...
- eNSP——利用三层交换机实现VLAN间路由
原理: VLAN将一个物理的LAN在逻辑上划分成多个广播域.VLAN内的主机间可以直接通信,而VLAN间不能直接互通. 在现实网络中,经常会遇到需要跨VLAN相互访问的情况,工程师通常会选择一些方法来 ...