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 Mapmap = Charset.availableCharsets();195 196 Set > set = map.entrySet();197 198 for (Map.Entry 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 }