Netty学习 2、通道(Channel)

通道(Channel)

一、通道(Channel)

通道(Channel)是NIO用来传输数据的。和流类似,只不过有很大的区别

区别:

  • ​ 通道用来传输的是数据块,也就是Buffer。而流用来传输字节的
  • ​ 通道可以同时进行读写,而流只能读或者只能写
  • ​ 通道可以实现异步读写数据
  • ​ 通道可以从缓冲读数据,也可以写数据到缓冲

二、常用的通道类

类名 作用
FileChannel 用于文件的数据读写
DatagramChannel 用于UDP的数据读写
ServerSocketChannel和SocketChannel 用于TCP的数据读写

三、FileChannel实列

package com.dashu.nio;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Set;

/**
 * 在NIO中,缓冲区就像高铁,通道就是高铁路,人就是数据。
 * 人坐高铁,高铁通过高铁路从贵阳到北京
 * 缓冲区存数据,通道传输缓冲区
 * 

* 一、通道(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的Feles工具类的newByteChannel() *

* 四、通道之间的数据传输 * transferFrom() * transferTo() *

* 五、分散(Scatter)与聚集(Gather) * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中 * 聚集写入(Gathering Writes):将多个缓冲去中的数据聚集到通道中 *

* 六、字符集:Charset * 编码:字符串 -> 字节数组 * 解码:字节数组 -> 字符串 */ public class NioChannel { public static void main(String[] args) throws CharacterCodingException { NioChannel nioChannel = new NioChannel(); } /** * 分散读取,和聚集写入 */ public void test04() { //输入文件 RandomAccessFile inRandomAccessFile = null; //输入文件通道 FileChannel inFileChannel = null; //输出通道 RandomAccessFile outRandomAccessFile = null; //输出文件通道 FileChannel outFileChannel = null; try { //创建输入文件 inRandomAccessFile = new RandomAccessFile("d:/a.txt", "rw"); //创建输入通道 inFileChannel = inRandomAccessFile.getChannel(); //缓冲区1 ByteBuffer byteBuffer1 = ByteBuffer.allocate(100); //缓冲区2 ByteBuffer byteBuffer2 = ByteBuffer.allocate(100); //缓冲区数组 ByteBuffer[] byteBuffers = {byteBuffer1, byteBuffer2}; //将输入通道中的数据写到缓冲区数组 inFileChannel.read(byteBuffers); //切换缓冲区数组中缓冲区的模式:读 for (ByteBuffer byteBuffer : byteBuffers) { byteBuffer.flip(); } //分别打印缓冲区中的数据 System.out.println(new String(byteBuffers[0].array(), 0, byteBuffers[0].limit())); System.out.println("-----------"); System.out.println(new String(byteBuffers[1].array(), 0, byteBuffers[1].limit())); //创建输出文件 outRandomAccessFile = new RandomAccessFile("d:/a2.txt", "rw"); //创建输出通道 outFileChannel = outRandomAccessFile.getChannel(); //将缓冲区数组的数据写到输出通道 outFileChannel.write(byteBuffers); } catch (Exception e) { e.printStackTrace(); } finally { //通道和文件输入流关闭关闭 if (outFileChannel != null) { try { outFileChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (outRandomAccessFile != null) { try { outRandomAccessFile.close(); } catch (Exception e) { e.printStackTrace(); } } if (inFileChannel != null) { try { inFileChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (inRandomAccessFile != null) { try { inRandomAccessFile.close(); } catch (Exception e) { e.printStackTrace(); } } } } /** * 通道之间的数据传输 */ public void test03() { //获取当前时间毫秒 long start = System.currentTimeMillis(); //获取文件输入通道 FileChannel inChannel = null; //获取文件输出通道 FileChannel outChannel = null; try { //创建文件输入通道(StandardOpenOption.READ:读) inChannel = FileChannel.open(Paths.get(""), StandardOpenOption.READ); //创建文件输出通道(StandardOpenOption.WRITE:写, StandardOpenOption.READ:读, StandardOpenOption.CREATE:文件不存在创建,文件存在覆盖) outChannel = FileChannel.open(Paths.get(""), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); //将输入文件通道的输据转移到输出文件通道 inChannel.transferTo(0, inChannel.size(), outChannel); //将输入文件通道的输据转移到输出文件通道 outChannel.transferFrom(inChannel, 0, inChannel.size()); } catch (Exception e) { e.printStackTrace(); } finally { //通道关闭 if (outChannel != null) { try { outChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (inChannel != null) { try { inChannel.close(); } catch (Exception e) { e.printStackTrace(); } } } //获取当前时间毫秒 long end = System.currentTimeMillis(); //输出 System.out.println("耗时:" + (end - start)); } /** * 利用通道完成文件的复制(直接缓冲区) */ public void test02() { //获取当前时间毫秒 long start = System.currentTimeMillis(); //文件输入通道 FileChannel inChannel = null; //文件输出通道 FileChannel outChannel = null; try { // 输入通道(StandardOpenOption.READ:读) inChannel = FileChannel.open(Paths.get("d:/a.txt"), StandardOpenOption.READ); // 输入通道(StandardOpenOption.WRITE:写, StandardOpenOption.READ:读, StandardOpenOption.CREATE:文件不存在创建,文件存在覆盖) outChannel = FileChannel.open(Paths.get("d:/a3.txt"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); //通过输入通道获取输入Buffer MappedByteBuffer inMappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); //通过输出通道获取输出Buffer MappedByteBuffer outMappedByteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size()); //创建byte数组 byte[] dst = new byte[inMappedByteBuffer.limit()]; //获取输入Buffer的数据保存到byte数组 inMappedByteBuffer.get(dst); //将byte数组的数据保存到输出Buffer outMappedByteBuffer.put(dst); } catch (Exception e) { //异常抛出 e.printStackTrace(); } finally { //通道关闭 if (outChannel != null) { try { outChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (inChannel != null) { try { inChannel.close(); } catch (Exception e) { e.printStackTrace(); } } } //获取当前时间毫秒 long end = System.currentTimeMillis(); //输出 System.out.println("耗时:" + (end - start)); } /** * 利用通道完成文件的复制(非直接缓冲区) */ public void test01() { //获取当前时间毫秒 long start = System.currentTimeMillis(); //文件输入流 FileInputStream fileInputStream = null; //文件输出流 FileOutputStream fileOutputStream = null; //文件输入通道 FileChannel inChannel = null; //文件输出通道 FileChannel outChannel = null; try { //输入文件 fileInputStream = new FileInputStream("d:/a.txt"); //输出文件 fileOutputStream = new FileOutputStream("d:/a2.txt"); //输入通道 inChannel = fileInputStream.getChannel(); //输出通道 outChannel = fileOutputStream.getChannel(); //创建缓存区 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //循环将”输入通道“中的数据读取到”缓存区“,然后将”缓存区“中的数据写入到”输出通道“ while (true) { //先清空缓存区 byteBuffer.clear(); //将”输入通道“中的数据读取(存入)到”缓存区“ int read = inChannel.read(byteBuffer); //判断”输入通道“中的数据是否读取完,读取完,退出循环 if (read == -1) { break; } //切换”缓存区“模式:读 byteBuffer.flip(); //将”缓存区“中的数据写到(存入)”输出通道“ outChannel.write(byteBuffer); } } catch (Exception e) { //异常抛出 e.printStackTrace(); } finally { //关闭通道和流 if (outChannel != null) { try { outChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (inChannel != null) { try { inChannel.close(); } catch (Exception e) { e.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } if (fileInputStream != null) { try { fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); } } } //获取当前时间毫秒 long end = System.currentTimeMillis(); //输出 System.out.println("耗时:" + (end - start)); } }

你可能感兴趣的:(Netty学习,java,NIO,Channel,Channel,Netty)