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 * 1、通道:用於源節點與目標節點的鏈接,在Java NIO中負責緩衝區中數據的傳輸。通道自己是不存儲任何數據的,所以須要配合緩衝區進行傳輸數據 22 * 2、通道的一些主要實現類 23 * java.nio.Channel接口 24 * |--FileChannel 25 * |--SocketChannel 26 * |--ServerSocketChannel 27 * |--DatagramChannel 28 * 3、獲取通道 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 * 4、通道之間的數據傳輸 39 * transferFrom() 40 * transferTo() 41 * 5、分散和彙集 42 * 分散度區:將通道中的數據分散到多個緩衝區中 43 * 彙集寫入:將多個緩衝區中的數據彙集到通道中 44 * 45 * 6、字符集: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 //二、利用直接緩衝區完成文件的複製(內存映射文件) 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 //一、利用通道完成文件的複製(費直接緩衝區) 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 }