一、通道(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的更多相关文章

  1. nio再学习之通道channel

    通道(Channel):用于在数据传输过程中,进行输入输出的通道,其与(流)Stream不一样,流是单向的,在BIO中我们分为输入流,输出流,但是在通道中其又具有读的功能也具有写的功能或者两者同时进行 ...

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

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

  3. NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件

    通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...

  4. 理解CNN中的通道 channel

    在深度学习的算法学习中,都会提到 channels 这个概念.在一般的深度学习框架的 conv2d 中,如 tensorflow .mxnet ,channels 都是必填的一个参数. channel ...

  5. go中的数据结构通道-channel

    1. channel的使用 很多文章介绍channel的时候都和并发揉在一起,这里我想把它当做一种数据结构来单独介绍它的实现原理. channel,通道.golang中用于数据传递的一种数据结构.是g ...

  6. 详解 通道 (Channel 接口)

    在本篇博文中,本人主要讲解NIO 的两个核心点 -- 缓冲区(Buffer) 和 通道 (Channel)之一的 缓冲区(Buffer), 有关NIO流的其他知识点请观看本人博文<详解 NIO流 ...

  7. Java NIO之通道Channel

    channel与流的区别: 流基于字节,且读写为单向的. 通道基于快Buffer,可以异步读写.除了FileChannel之外都是双向的. channel的主要实现: FileChannel Data ...

  8. go实例之轻量级线程goroutine、通道channel与select

    1.goroutine线程 goroutine是一个轻量级的执行线程.假设有一个函数调用f(s),要在goroutine中调用此函数,请使用go f(s). 这个新的goroutine将与调用同时执行 ...

  9. Java-NIO(四):通道(Channel)的原理与获取

    通道(Channel): 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Chann ...

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

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

随机推荐

  1. mysql逻辑备份mydumper

      mydumper是一个针对MySQL的高性能多线程备份和恢复工具,它提供了并发备份功能,备份效率有很大提高. 安装mydumper yum安装 # rpm -ivh https://github. ...

  2. JEECG新建用户不用系统用户表的实现

    首先新增组织机构 和 角色: -- 新增 组织机构 INSERT INTO `t_s_depart` VALUES ('dept001', '你所在的机构', '你所在的机构的描述', null, ' ...

  3. git rev-parse介绍;获取commit id

    git rev-parse master^{commit} 是什么意思 显示master提交的SHA1值 if you want to make sure that the output actual ...

  4. pipeline代码自动生成

    如图所示,安装完插件后,Sample Step里就有相应的选项,选择某个选项后,点击Generate Pipeline Script按钮,就可以自动生成代码片段,然后放入pipeline流水线里就可以 ...

  5. jenkins插件Configuration Slicing plugin批量修改配置

    作用 批量修改jenkins上job配置

  6. JAVA数据结构和算法 1-综述:数据结构和数据类型

    数据结构:指数据在计算机内存空间中或者磁盘中的组织形式. 对于数据结构的操作:插入.删除.查找.迭代遍历.排序等: Java.util包中含有诸如向量(一个可扩充的数组).栈.哈希表等类型的数据结构, ...

  7. CF1227C Messy

    思路: 构造题.首先把字符串变成“(((((...)))))”的样子,再根据k的取值变成“()()()...((...))”的样子即可. 实现: #include <bits/stdc++.h& ...

  8. Npcap.例子(raw tcp syn)

    1.来自:winpcap实现syn攻击 - 125096 - CSDN博客.html(https://blog.csdn.net/qq125096885/article/details/5178452 ...

  9. Net上传文件

    Net上传文件 最近工作内容涉及到一点前端的内容,把学习到的内容记录下来,在今后的开发过程中,不要犯错.本篇只针对一些刚入职的小白及前端开发人员,大牛请绕道!~ 刚开始我们先不讲上传文件的防范问题,先 ...

  10. Ubuntu将自带的python3升级

    一.这里演示的是将python3.5升级到python3.6 1.添加安装源,在命令行输入如下命令: sudo add-apt-repository ppa:jonathonf/python-3.6 ...