NIO之Channel聚集(gather)写入与分散(scatter)读取详解编程语言

Channel聚集(gather)写入

聚集写入( Gathering Writes)是指将多个 Buffer 中的数据“聚集”到 Channel。 特别注意:按照缓冲区的顺序,写入 position 和 limit 之间的数据到 Channel 。 

NIO之Channel聚集(gather)写入与分散(scatter)读取详解编程语言

Channel分散(scatter)读取

分散读取( Scattering Reads)是指从 Channel 中读取的数据“分散” 到多个 Buffer 中。 特别注意:按照缓冲区的顺序,从 Channel 中读取的数据依次将 Buffer 填满。

NIO之Channel聚集(gather)写入与分散(scatter)读取详解编程语言

 

聚集写入( Gathering Writes和分散读取( Scattering Reads)代码示例

  1 package com.expgiga.NIO; 
  2  
  3 import java.io.FileInputStream; 
  4 import java.io.FileOutputStream; 
  5 import java.io.IOException; 
  6 import java.io.RandomAccessFile; 
  7 import java.nio.ByteBuffer; 
  8 import java.nio.CharBuffer; 
  9 import java.nio.MappedByteBuffer; 
 10 import java.nio.channels.FileChannel; 
 11 import java.nio.charset.Charset; 
 12 import java.nio.charset.CharsetDecoder; 
 13 import java.nio.charset.CharsetEncoder; 
 14 import java.nio.file.Paths; 
 15 import java.nio.file.StandardOpenOption; 
 16 import java.util.Map; 
 17 import java.util.Set; 
 18  
 19 /** 
 20  * 一、Channel:用于源节点与目标节点之间的连接。在Java NIO中,负责缓冲区中数据传输,Channel本身不存储数据,因此需要配合缓冲区进行传输。 
 21  * 
 22  * 二、Channel的实现类: 
 23  *     java.nio.channels.Channel 接口: 
 24  *     |-- FileChannel 
 25  *     |-- SocketChannel 
 26  *     |-- ServerSocketChannel 
 27  *     |-- DatagramChannel 
 28  * 
 29  * 三、获取通道Channel 
 30  * 1.Java针对支持通道的类提供了getChannel()方法 
 31  *   本地IO 
 32  *   FileInputStream/FileOutputStream 
 33  *   RandomAccessFile 
 34  * 
 35  *   网络IO: 
 36  *   Socket 
 37  *   ServerSocket 
 38  *   DatagramSocket 
 39  * 
 40  * 2.在jdk1.7中的NIO.2针对各个通道提供了静态方法open() 
 41  * 
 42  * 3.在jdk1.7中的NIO.2的Files工具类的newByteChannel() 
 43  * 
 44  * 四、通道之间的数据传输 
 45  * transferFrom() 
 46  * transferTo() 
 47  * 
 48  * 五、分散(scatter)与聚集(gather) 
 49  * 分散读取(scattering Reads):将通道中的数据分散到多个缓冲区中 
 50  * 聚集写入(gathering Writes):将多个缓冲区的数据聚集到通道中 
 51  * 
 52  * 六、字符集Charset 
 53  * 编码:字符串->字节数组 
 54  * 解码:字节数组 -> 字符串 
 55  * 
 56  */ 
 57 public class TestChannel { 
 58  
 59     public static void main(String[] args) throws IOException { 
 60  
 61         /* 
 62          * 1.利用通道完成文件的复制(非直接缓冲区) 
 63          */ 
 64         FileInputStream fis = null; 
 65         FileOutputStream fos = null; 
 66  
 67         FileChannel inChannel = null; 
 68         FileChannel outChannel = null; 
 69  
 70         try { 
 71             fis = new FileInputStream("1.jpg"); 
 72             fos = new FileOutputStream("2.jpg"); 
 73             //1.获取通道 
 74             inChannel = fis.getChannel(); 
 75             outChannel = fos.getChannel(); 
 76  
 77             //2.分配指定大小的缓冲区 
 78             ByteBuffer buffer = ByteBuffer.allocate(1024); 
 79  
 80             //3.将通道中的数据缓冲区中 
 81             while (inChannel.read(buffer) != -1) { 
 82  
 83                 buffer.flip();//切换成都数据模式 
 84  
 85                 //4.将缓冲区中的数据写入通道中 
 86                 outChannel.write(buffer); 
 87                 buffer.clear();//清空缓冲区 
 88             } 
 89         } catch (Exception e) { 
 90             e.printStackTrace(); 
 91         } finally { 
 92             if (outChannel != null) { 
 93                 try { 
 94                     outChannel.close(); 
 95                 } catch (IOException e) { 
 96                     e.printStackTrace(); 
 97                 } 
 98             } 
 99  
100             if (inChannel != null) { 
101                 try { 
102                     inChannel.close(); 
103                 } catch (IOException e) { 
104                     e.printStackTrace(); 
105                 } 
106             } 
107  
108             if (fis != null) { 
109                 try { 
110                     fis.close(); 
111                 } catch (IOException e) { 
112                     e.printStackTrace(); 
113                 } 
114             } 
115  
116             if (fos != null) { 
117                 try { 
118                     fos.close(); 
119                 } catch (IOException e) { 
120                     e.printStackTrace(); 
121                 } 
122             } 
123         } 
124  
125  
126         /* 
127          * 2.利用(直接缓冲区)通道完成文件的复制(内存映射文件的方式) 
128          */ 
129  
130         long start = System.currentTimeMillis(); 
131         FileChannel inChannel2 = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); 
132         FileChannel outChannel2 = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); 
133  
134         //内存映射文件 
135         MappedByteBuffer inMappedBuf = inChannel2.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); 
136         MappedByteBuffer outMappedBuf = outChannel2.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size()); 
137  
138         //直接对缓冲区进行数据读写操作 
139         byte[] dst = new byte[inMappedBuf.limit()]; 
140         inMappedBuf.get(dst); 
141         outMappedBuf.put(dst); 
142  
143         inChannel2.close(); 
144         outChannel2.close(); 
145  
146         long end = System.currentTimeMillis(); 
147         System.out.println("耗费的时间为:" + (end - start)); 
148  
149         /* 
150          * 通道之间的数据传输(直接缓冲区) 
151          */ 
152         FileChannel inChannel3 = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); 
153         FileChannel outChannel3 = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); 
154  
155         inChannel3.transferTo(0, inChannel3.size(), outChannel3); 
156         //等价于 
157 //        outChannel3.transferFrom(inChannel3, 0, inChannel3.size()); 
158  
159         inChannel3.close(); 
160         outChannel3.close(); 
161  
162         /* 
163          * 分散和聚集 
164          */ 
165         RandomAccessFile randomAccessFile1 = new RandomAccessFile("1.txt", "rw"); 
166  
167         //1.获取通道 
168         FileChannel fileChannel1 = randomAccessFile1.getChannel(); 
169  
170         //2.分配指定大小的缓冲区 
171         ByteBuffer buf1 = ByteBuffer.allocate(100); 
172         ByteBuffer buf2 = ByteBuffer.allocate(2014); 
173  
174         //3.分散读取 
175         ByteBuffer[] bufs = {buf1, buf2}; 
176         fileChannel1.read(bufs); 
177  
178         for (ByteBuffer byteBuffer : bufs) { 
179             byteBuffer.flip(); 
180         } 
181         System.out.println(new String(bufs[0].array(), 0, bufs[0].limit())); 
182         System.out.println("----------------------------"); 
183         System.out.println(new String(bufs[1].array(), 0, bufs[1].limit())); 
184  
185         //4.聚集写入 
186         RandomAccessFile randomAccessFile2 = new RandomAccessFile("2.txt", "rw"); 
187         FileChannel fileChannel2 = randomAccessFile2.getChannel(); 
188         fileChannel2.write(bufs); 
189  
190  
191         /* 
192          * 字符集 
193          */ 
194         Map<String, Charset> map = Charset.availableCharsets(); 
195  
196         Set<Map.Entry<String, Charset>> set = map.entrySet(); 
197  
198         for (Map.Entry<String, Charset> entry : set) { 
199             System.out.println(entry.getKey() + "=" + entry.getValue()); 
200         } 
201  
202  
203  
204         Charset cs1 = Charset.forName("GBK"); 
205         //获取编码器和解码器 
206         CharsetEncoder ce = cs1.newEncoder(); 
207  
208         //获取解码器 
209         CharsetDecoder cd = cs1.newDecoder(); 
210  
211         CharBuffer cBuf = CharBuffer.allocate(1024); 
212         cBuf.put("hello world!"); 
213         cBuf.flip(); 
214  
215         //编码 
216         ByteBuffer bBuf = ce.encode(cBuf); 
217  
218         for (int i = 0; i < 12; i++) { 
219             System.out.println(bBuf.get()); 
220         } 
221  
222         //解码 
223         bBuf.flip(); 
224         CharBuffer cBuf2 = cd.decode(bBuf); 
225         System.out.println(cBuf2.toString()); 
226  
227         System.out.println("----------------------------"); 
228         Charset cs2 = Charset.forName("UTF-8"); //"GBK" 
229         bBuf.flip(); 
230         CharBuffer cBuf3 = cs2.decode(bBuf); 
231         System.out.println(cBuf3); 
232     } 
233 }

 

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/15743.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论