- Channel聚集(gather)写入:
聚集写入( Gathering Writes)是指将多个 Buffer 中的数据“聚集”到 Channel。 特别注意:按照缓冲区的顺序,写入 position 和 limit 之间的数据到 Channel 。
- Channel分散(scatter)读取:
分散读取( Scattering Reads)是指从 Channel 中读取的数据“分散” 到多个 Buffer 中。 特别注意:按照缓冲区的顺序,从 Channel 中读取的数据依次将 Buffer 填满。
-
聚集写入( 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 }