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 }