通道(Channel)的原理与获取
Posted 林淼零
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通道(Channel)的原理与获取相关的知识,希望对你有一定的参考价值。
通道(Channel):由 java.nio.channels 包定义 的。Channel 表示 IO 源与目标打开的连接。
Channel 类似于传统的“流”。只不过 Channel 本身不能直接访问数据,Channel 只能与 Buffer 进行交互
TestChannel
package com.aff.nio; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import org.junit.Test; /* * 1.通道(channel):用于源节点于目标节点的连接,在Java NIO中负责缓冲区数据的传输。 * channel本身不存储数据的,因此需要配合缓冲区传输‘ * 2.通道的主要实现类 * java.nio.channels.Channel接口 * |FileChannel 本地的文件通道 * |SocketChannel 网络 TCP * |ServerSocketChannel 网络TCP * |DatagramChannel 网络 UDP * * 3.获取通道 * ①.java针对支持通道的类提供了getChannel()方法 * * 本地: * FileInputStream/FileOutputStream * RandomAccessFile//随机存储文件流 * * 网络IO: * Socket * ServerSocket * DatagremSocket * * ②.jdk1.7NIO.2针对各个通道提供静态方法open() * ③.jdk1.7中的NIO.2的Files工具类的newByteChannel() * 4.通道之间的数据传输 * transferFrom() * transferTo() * * 5. * 分散(Scatter)与聚集(Gather) * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中 * 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中 * * 6.字符集:Charset * 编码:字符串->字节数组 * 解码:字节数组->字符串 */ public class TestChannel { // 分散和聚集 @Test public void test4() throws IOException { RandomAccessFile raf = new RandomAccessFile("11.txt", "rw"); // 分散读取,通道中数据分散到多个缓冲区中 // 1.获取通道 FileChannel channel = raf.getChannel(); // 2.分配通道大小 ByteBuffer buf1 = ByteBuffer.allocate(100); ByteBuffer buf2 = ByteBuffer.allocate(500); // 3.分散读取 ByteBuffer[] bufs = { buf1, buf2 }; channel.read(bufs); for (ByteBuffer by : bufs) { by.flip(); } System.out.println(new String(bufs[0].array(), 0, bufs[0].limit())); System.out.println("================="); System.out.println(new String(bufs[1].array(), 0, bufs[1].limit())); // 4.聚集写入 RandomAccessFile raf2 = new RandomAccessFile("16.txt", "rw"); FileChannel channel2 = raf2.getChannel(); channel2.write(bufs); } // 通道之间的数据传输(直接缓冲区) @Test public void test3() throws IOException { FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("4.jpg"),
StandardOpenOption.WRITE,
StandardOpenOption.READ,StandardOpenOption.CREATE);
inChannel.transferTo(0, inChannel.size(), outChannel);
// 从inchannel来到outchannel中去 // inChannel.transferTo(position, count, target) // outChannel.transferFrom(inChannel, 0, inChannel.size()); // outChannel.transferFrom(src, position, count) } // 使用直接缓冲区完成文件的复制(内存映射文件的方) @Test public void test2() throws Exception { long start = System.currentTimeMillis(); FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("3.jpg"),
StandardOpenOption.WRITE,StandardOpenOption.READ,
StandardOpenOption.CREATE); // 内存映射文件 MappedByteBuffer inMappedByteBuffer = inChannel.map(MapMode.READ_ONLY, 0,
inChannel.size()); MappedByteBuffer outMappedByteBuffer = outChannel.map(MapMode.READ_WRITE, 0,
inChannel.size()); // 直接对缓冲区进行数据的读写操作 byte[] dst = new byte[inMappedByteBuffer.limit()]; inMappedByteBuffer.get(dst); outMappedByteBuffer.put(dst); inChannel.close(); outChannel.close(); long end = System.currentTimeMillis(); System.out.println("时间为:" + (end - start));// 7 } // 使用通道完成文件的复制(非直接缓冲区) @Test public void test1() throws FileNotFoundException { long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; FileChannel inchannel = null; FileChannel outchannel = null; try { fis = new FileInputStream("1.jpg"); fos = new FileOutputStream("2.jpg"); // 1.获取通道 inchannel = fis.getChannel(); outchannel = fos.getChannel(); // 2.分配指定大小的缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); // 3.将通道中的数据存入缓冲区中 while ((inchannel.read(buf)) != -1) { buf.flip(); // 然后切换成读取模式,再输出 // 4.将缓冲区的数据写入通道中 outchannel.write(buf); buf.clear();// 清空缓冲区 } } catch (IOException e) { e.printStackTrace(); } finally { if (outchannel != null) { try { outchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (inchannel != null) { try { inchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } long end = System.currentTimeMillis(); System.out.println("时间为:" + (end - start));// 146 } }
以上是关于通道(Channel)的原理与获取的主要内容,如果未能解决你的问题,请参考以下文章
NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
获取一个类别Channel的权限并设置为语音通道discord.py
Kotlin 协程Channel 通道 ⑤ ( BroadcastChannel 广播通道 | 代码示例 )
Java NIO三组件——Selecotr/Channel实现原理解析
Java NIO三组件——Selecotr/Channel实现原理解析
Kotlin 协程Channel 通道 ④ ( Channel 通道的热数据流属性 | Channel 通道关闭过程 | Channel 通道关闭代码示例 )