zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件详解编程语言

2023-06-13 09:20:45 时间
通道(Channel)

由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channel只能与Buffer进行交互。通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件、套接字 ),反之亦然;通道是访问IO服务的导管,通过通道,我们可以以最小的开销来访问操作系统的I/O服务;顺便说下,缓冲区是通道内部发送数据和接收数据的端点。

在标准的IO当中,都是基于字节流/字符流进行操作的,而在NIO中则是是基于Channel和Buffer进行操作,其中的Channel的虽然模拟了流的概念,实则大不相同。


内存和IO接口之间加了 DMA(直接存储器),DMA向CPU申请权限,IO的操作全部由DMA管理。CPU不要干预。
早一代IO操作是由CPU负责IO接口

NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件详解编程语言

新一代DMA授权处理IO接口

NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件详解编程语言

通道(Channel)模式

NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件详解编程语言

 1 package com.expgiga.NIO; 

 3 import java.io.FileInputStream; 

 4 import java.io.FileOutputStream; 

 5 import java.io.IOException; 

 6 import java.nio.ByteBuffer; 

 7 import java.nio.MappedByteBuffer; 

 8 import java.nio.channels.FileChannel; 

 9 import java.nio.file.Paths; 

 10 import java.nio.file.StandardOpenOption; 

 12 /** 

 13 * 一、Channel:用于源节点与目标节点之间的连接。在Java NIO中,负责缓冲区中数据传输,Channel本身不存储数据,因此需要配合缓冲区进行传输。 

 14 * 

 15 * 二、Channel的实现类: 

 16 * java.nio.channels.Channel 接口: 

 17 * |-- FileChannel 

 18 * |-- SocketChannel 

 19 * |-- ServerSocketChannel 

 20 * |-- DatagramChannel 

 21 * 

 22 * 三、获取通道Channel 

 23 * 1.Java针对支持通道的类提供了getChannel()方法 

 24 * 本地IO 

 25 * FileInputStream/FileOutputStream 

 26 * RandomAccessFile 

 27 * 

 28 * 网络IO: 

 29 * Socket 

 30 * ServerSocket 

 31 * DatagramSocket 

 32 * 

 33 * 2.在jdk1.7中的NIO.2针对各个通道提供了静态方法open() 

 34 * 

 35 * 3.在jdk1.7中的NIO.2的Files工具类的newByteChannel() 

 36 * 

 37 * 四、通道之间的数据传输 

 38 * transferFrom() 

 39 * transferTo() 

 40 * 

 41 */ 

 42 public class TestChannel { 

 44 public static void main(String[] args) throws IOException { 

 46 /* 

 47 * 1.利用通道完成文件的复制(非直接缓冲区) 

 48 */ 

 49 FileInputStream fis = null; 

 50 FileOutputStream fos = null; 

 52 FileChannel inChannel = null; 

 53 FileChannel outChannel = null; 

 55 try { 

 56 fis = new FileInputStream("1.jpg"); 

 57 fos = new FileOutputStream("2.jpg"); 

 58 //1.获取通道 

 59 inChannel = fis.getChannel(); 

 60 outChannel = fos.getChannel(); 

 62 //2.分配指定大小的缓冲区 

 63 ByteBuffer buffer = ByteBuffer.allocate(1024); 

 65 //3.将通道中的数据缓冲区中 

 66 while (inChannel.read(buffer) != -1) { 

 68 buffer.flip();//切换成都数据模式 

 70 //4.将缓冲区中的数据写入通道中 

 71 outChannel.write(buffer); 

 72 buffer.clear();//清空缓冲区 

 73 } 

 74 } catch (Exception e) { 

 75 e.printStackTrace(); 

 76 } finally { 

 77 if (outChannel != null) { 

 78 try { 

 79 outChannel.close(); 

 80 } catch (IOException e) { 

 81 e.printStackTrace(); 

 82 } 

 83 } 

 85 if (inChannel != null) { 

 86 try { 

 87 inChannel.close(); 

 88 } catch (IOException e) { 

 89 e.printStackTrace(); 

 90 } 

 91 } 

 93 if (fis != null) { 

 94 try { 

 95 fis.close(); 

 96 } catch (IOException e) { 

 97 e.printStackTrace(); 

 98 } 

 99 } 

101 if (fos != null) { 

102 try { 

103 fos.close(); 

104 } catch (IOException e) { 

105 e.printStackTrace(); 

106 } 

107 } 

108 } 

111 /* 

112 * 2.利用(直接缓冲区)通道完成文件的复制(内存映射文件的方式) 

113 */ 

115 long start = System.currentTimeMillis(); 

116 FileChannel inChannel2 = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); 

117 FileChannel outChannel2 = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); 

119 //内存映射文件 

120 MappedByteBuffer inMappedBuf = inChannel2.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); 

121 MappedByteBuffer outMappedBuf = outChannel2.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size()); 

123 //直接对缓冲区进行数据读写操作 

124 byte[] dst = new byte[inMappedBuf.limit()]; 

125 inMappedBuf.get(dst); 

126 outMappedBuf.put(dst); 

128 inChannel2.close(); 

129 outChannel2.close(); 

131 long end = System.currentTimeMillis(); 

132 System.out.println("耗费的时间为:" + (end - start)); 

134 /* 

135 * 通道之间的数据传输(直接缓冲区) 

136 */ 

137 FileChannel inChannel3 = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); 

138 FileChannel outChannel3 = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); 

140 inChannel3.transferTo(0, inChannel3.size(), outChannel3); 

141 //等价于 

142 // outChannel3.transferFrom(inChannel3, 0, inChannel3.size()); 

144 inChannel3.close(); 

145 outChannel3.close(); 

146 } 

147 }

 

15744.html

cjavamac