NIO系列——通道(Channel)

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