1 package com.slp.nio; 2 3 import org.junit.Test; 4 5 import java.io.*; 6 import java.nio.ByteBuffer; 7 import java.nio.CharBuffer; 8 import java.nio.MappedByteBuffer; 9 import java.nio.channels.FileChannel; 10 import java.nio.charset.CharacterCodingException; 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 * Created by sanglp on 2017/3/1. 21 * 一、通道:用于源节点与目标节点的连接,在Java NIO中负责缓冲区中数据的传输。通道本身是不存储任何数据的,因此需要配合缓冲区进行传输数据 22 * 二、通道的一些主要实现类 23 * java.nio.Channel接口 24 * |--FileChannel 25 * |--SocketChannel 26 * |--ServerSocketChannel 27 * |--DatagramChannel 28 * 三、获取通道 29 * 1.java针对支持通道的类提供了getChannel()方法 30 * 本地IO: 31 * FileInputStream/FileOutputStream/RandomAccessFile 32 * 网络IO: 33 * Socket 34 * ServerSocket 35 * DategramSocket 36 * 2.在jdk1.7中的NIO2针对各个通道提供了一个静态方法open() 37 * 3。jdk1.7中的NIO2的Files工具类的newByteChannel() 38 * 四、通道之间的数据传输 39 * transferFrom() 40 * transferTo() 41 * 五、分散和聚集 42 * 分散度区:将通道中的数据分散到多个缓冲区中 43 * 聚集写入:将多个缓冲区中的数据聚集到通道中 44 * 45 * 六、字符集:Charset 46 * 编码:字符串->字节数组 47 * 解码:字节数组->字符串 48 */ 49 public class TestChannel { 50 @Test 51 public void test6() throws CharacterCodingException { 52 Charset cs1 = Charset.forName("GBK"); 53 //获取编码器和解码器 54 CharsetEncoder ce = cs1.newEncoder(); 55 //获取解码器 56 CharsetDecoder cd = cs1.newDecoder(); 57 58 CharBuffer charBuffer = CharBuffer.allocate(1024); 59 charBuffer.put("桑丽平加油!!"); 60 charBuffer.flip(); 61 62 //编码 63 ByteBuffer byteBuffer = ce.encode(charBuffer); 64 for (int i=0;i<12;i++){ 65 System.out.println(byteBuffer.get(i)); 66 } 67 68 //解码 69 byteBuffer.flip(); 70 CharBuffer charBuffer1 = cd.decode(byteBuffer); 71 System.out.println(charBuffer1.toString()); 72 73 System.out.println("------------------------"); 74 75 Charset cs2 = Charset.forName("UTF-8"); 76 byteBuffer.flip(); 77 CharBuffer cBuf3 =cs2.decode(byteBuffer); 78 System.out.println(cBuf3.toString()); 79 } 80 81 @Test 82 public void test5(){ 83 Map<String,Charset> map=Charset.availableCharsets(); 84 Set<Map.Entry<String,Charset>> set = map.entrySet(); 85 for (Map.Entry<String,Charset> entry :set ){ 86 System.out.println(entry.getKey()+"="+entry.getValue()); 87 } 88 } 89 @Test 90 public void test4() throws IOException { 91 RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt","rw"); 92 //获取通道 93 FileChannel channel = randomAccessFile.getChannel(); 94 //分配指定大小的缓冲区 95 ByteBuffer buffer1 = ByteBuffer.allocate(100); 96 ByteBuffer buffer2 = ByteBuffer.allocate(1024); 97 //分散读取 98 ByteBuffer [] bufs = {buffer1,buffer2}; 99 channel.read(bufs); 100 for (ByteBuffer byteBuffer:bufs){ 101 byteBuffer.flip(); 102 } 103 104 System.out.println(new String(bufs[0].array(),0,bufs[0].limit())); 105 System.out.println("---------------"); 106 System.out.println(new String(bufs[1].array(),0,bufs[1].limit())); 107 108 //聚集写入 109 RandomAccessFile randomAccessFile1 = new RandomAccessFile("2.txt","rw"); 110 FileChannel channel1 = randomAccessFile1.getChannel(); 111 channel1.write(bufs); 112 113 } 114 115 //通道之间的数据传输(直接缓冲区) 116 @Test 117 public void test3() throws IOException { 118 FileChannel fileChannel = FileChannel.open(Paths.get("pipe.bmp"), StandardOpenOption.READ); 119 FileChannel outChannel =FileChannel.open(Paths.get("4.bmp"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW); 120 121 fileChannel.transferTo(0,fileChannel.size(),outChannel); 122 //outChannel.transferFrom(fileChannel,0,fileChannel.size());或者 123 fileChannel.close(); 124 outChannel.close(); 125 } 126 127 //2、利用直接缓冲区完成文件的复制(内存映射文件) 128 @Test 129 public void test2() throws IOException { 130 FileChannel fileChannel = FileChannel.open(Paths.get("pipe.bmp"), StandardOpenOption.READ); 131 FileChannel outChannel =FileChannel.open(Paths.get("3.bmp"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW); 132 //内存映射文件 133 MappedByteBuffer imMappedBuf = fileChannel.map(FileChannel.MapMode.READ_ONLY,0,fileChannel.size()); 134 MappedByteBuffer outMappedBuf = outChannel.map(FileChannel.MapMode.READ_WRITE,0,fileChannel.size()); 135 //直接对缓冲区进行数据的读写操作 136 byte [] dst = new byte[imMappedBuf.limit()]; 137 imMappedBuf.get(dst); 138 outMappedBuf.put(dst); 139 140 fileChannel.close(); 141 outChannel.close(); 142 143 } 144 145 //1、利用通道完成文件的复制(费直接缓冲区) 146 @org.junit.Test 147 public void test1(){ 148 FileInputStream fis =null; 149 FileOutputStream fos =null; 150 FileChannel inChanne=null; 151 FileChannel outChannel=null; 152 try{ 153 fis = new FileInputStream("pipe.bmp"); 154 fos = new FileOutputStream("2.jpg"); 155 //获取通道 156 inChanne =fis.getChannel(); 157 outChannel = fos.getChannel(); 158 //分配指定大小的缓冲区 159 ByteBuffer buffer = ByteBuffer.allocate(1024); 160 //将通道中的数据存入缓冲区中 161 while (inChanne.read(buffer)!=-1) { 162 buffer.flip();//切换为读取数据的模式 163 //将缓冲区中的数据写入通道 164 outChannel.write(buffer); 165 buffer.clear();//清空缓冲区 166 } 167 }catch (IOException e){ 168 e.printStackTrace(); 169 }finally { 170 if(outChannel!=null){ 171 try { 172 outChannel.close(); 173 } catch (IOException e) { 174 e.printStackTrace(); 175 } 176 } 177 if(inChanne!=null){ 178 try { 179 inChanne.close(); 180 } catch (IOException e) { 181 e.printStackTrace(); 182 } 183 } 184 185 if(fis!=null){ 186 try { 187 fis.close(); 188 } catch (IOException e) { 189 e.printStackTrace(); 190 } 191 } 192 if(fos!=null){ 193 try { 194 fos.close(); 195 } catch (IOException e) { 196 e.printStackTrace(); 197 } 198 } 199 } 200 201 } 202 }