内容来自:java nio线程精讲
NIO简介
NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件读写操作
IO和NIO的区别
| IO |
NIO |
| 面向流 |
面向缓冲区 |
| 阻塞IO |
非阻塞IO |
| 无 |
选择器 |
NIO的核心在于:通道(channel)和缓冲区(buffer)。通道表示打开到IO设备的连接。如需要使用NIO系统,需要获取用于IO设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。
缓冲区
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
public class TestBuffer { @Test public void test1() { String str = "abcd"; ByteBuffer buffer = ByteBuffer.allocate(1024);
System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity());
System.out.println("-----------------------"); buffer.put(str.getBytes());
System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
buffer.flip(); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
byte[] rs = new byte[buffer.limit()]; buffer.get(rs); System.out.println(new String(rs));
System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
buffer.rewind(); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
buffer.clear(); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------"); }
@Test public void test2() { String str = "abcd"; ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put(str.getBytes()); buffer.flip(); byte[] bytes = new byte[buffer.limit()]; buffer.get(bytes, 0, 2); System.out.println(new String(bytes)); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
buffer.mark();
buffer.get(bytes, 2, 2); System.out.println(new String(bytes,2,2)); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
buffer.reset(); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); System.out.println("-----------------------");
if (buffer.hasRemaining()) {
System.out.println(buffer.remaining()); } } }
|
通道(Channel)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
public class TestChannel {
@Test public void test1() { FileInputStream inputStream = null; FileOutputStream outputStream = null;
FileChannel inChannel = null; FileChannel outChannel = null;
try { inputStream = new FileInputStream("D:\\IdeaProject\\Nio\\src\\main\\resources\\1.png"); outputStream = new FileOutputStream("D:\\IdeaProject\\Nio\\src\\main\\resources\\2.png");
inChannel = inputStream.getChannel(); outChannel = outputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) { buffer.flip(); outChannel.write(buffer); buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } finally { if (outChannel != null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (inChannel != null) { try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Test public void test2() { FileChannel inChannel = null; FileChannel outChannel = null; try { inChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\1.png"), StandardOpenOption.READ); outChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\2.png"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
MappedByteBuffer inBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); MappedByteBuffer outBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
byte[] rs = new byte[inBuffer.limit()]; inBuffer.get(rs); outBuffer.put(rs); } catch (IOException e) { e.printStackTrace(); } finally { if (inChannel != null) { try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (outChannel != null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Test public void test3() throws IOException { FileChannel inChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\1.png"), StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\2.png"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
inChannel.transferTo(0, inChannel.size(), outChannel); inChannel.close(); outChannel.close(); }
@Test public void test4() throws IOException { RandomAccessFile raf1 = new RandomAccessFile("D:\\IdeaProject\\Nio\\src\\main\\resources\\1.txt", "rw");
FileChannel channel = raf1.getChannel();
ByteBuffer buf1 = ByteBuffer.allocate(1); ByteBuffer buf2 = ByteBuffer.allocate(2);
ByteBuffer[] bufs = {buf1, buf2}; channel.read(bufs);
for (ByteBuffer byteBuffer : bufs) { byteBuffer.flip(); }
System.out.println(new String(bufs[0].array(), 0, bufs[0].limit())); System.out.println("------------------"); System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));
RandomAccessFile raf2 = new RandomAccessFile("D:\\IdeaProject\\Nio\\src\\main\\resources\\2.txt", "rw"); FileChannel wChannel = raf2.getChannel(); wChannel.write(bufs); }
@Test public void test5() { SortedMap<String, Charset> map = Charset.availableCharsets(); Set<Map.Entry<String, Charset>> set = map.entrySet();
for (Map.Entry<String, Charset> entry : set) { System.out.println(entry.getKey() + "=" + entry.getValue()); } }
@Test public void test6() throws CharacterCodingException { Charset gbk = Charset.forName("GBK");
CharsetEncoder encoder = gbk.newEncoder();
CharsetDecoder decoder = gbk.newDecoder();
CharBuffer charBuffer = CharBuffer.allocate(1024); charBuffer.put("测试!"); charBuffer.flip();
ByteBuffer eBuf = encoder.encode(charBuffer); for (int i = 0; i < 5; i++) { System.out.println(eBuf.get()); }
eBuf.flip(); CharBuffer cbuf = decoder.decode(eBuf); System.out.println(cbuf.toString()); } }
|
阻塞式NIO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| @Test public void client() throws IOException { SocketChannel channel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999)); FileChannel inChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\1.png"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) { buffer.flip(); channel.write(buffer); buffer.clear(); }
channel.shutdownOutput();
int len = 0; while ((len = channel.read(buffer)) != -1) { buffer.flip(); System.out.println(new String(buffer.array(), 0, len)); buffer.clear(); }
inChannel.close(); channel.close(); }
@Test public void server() throws IOException { ServerSocketChannel channel = ServerSocketChannel.open(); FileChannel outChannel = FileChannel.open(Paths.get("D:\\IdeaProject\\Nio\\src\\main\\resources\\2.png"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
channel.bind(new InetSocketAddress(9999));
SocketChannel acceptChannel = channel.accept();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (acceptChannel.read(buffer) != -1) { buffer.flip(); outChannel.write(buffer); buffer.clear(); }
buffer.put("接受成功".getBytes()); buffer.flip(); acceptChannel.write(buffer);
acceptChannel.close(); outChannel.close(); channel.close(); }
|
非阻塞式NIO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| @Test public void client() throws IOException { SocketChannel channel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
channel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) { String str = scan.next(); buffer.put((new Date().toString() + "\n" + str).getBytes()); buffer.flip(); channel.write(buffer); buffer.clear(); }
channel.close(); }
@Test public void server() throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(9999));
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) { SelectionKey key = iterator.next();
if (key.isAcceptable()) { SocketChannel aChannel = serverChannel.accept();
aChannel.configureBlocking(false);
aChannel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel sChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024); int len = 0; while ((len = sChannel.read(buffer)) > 0) { buffer.flip(); System.out.println(new String(buffer.array(), 0, len)); buffer.clear(); } } iterator.remove(); } } }
|
非阻塞式NIO(UDP)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @Test public void send() throws IOException { DatagramChannel channel = DatagramChannel.open(); channel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String str = scanner.next(); buffer.put((new Date().toString() + "\n" + str).getBytes()); buffer.flip(); channel.send(buffer, new InetSocketAddress("127.0.0.1", 9999)); buffer.clear(); }
channel.close(); }
@Test public void receive() throws IOException { DatagramChannel channel = DatagramChannel.open(); channel.configureBlocking(false);
channel.bind(new InetSocketAddress(9999));
Selector selector = Selector.open(); channel.register(selector, SelectionKey.OP_READ);
while (selector.select() > 0) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey sk = iterator.next();
if (sk.isReadable()) { ByteBuffer buffer = ByteBuffer.allocate(1024); channel.receive(buffer); buffer.flip(); System.out.println(new String(buffer.array(), 0, buffer.limit())); } }
iterator.remove(); } }
|
管道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Test public void test1() throws IOException { Pipe pipe = Pipe.open();
ByteBuffer buffer = ByteBuffer.allocate(1024);
Pipe.SinkChannel sinkChannel = pipe.sink();
buffer.put("数据".getBytes()); buffer.flip(); sinkChannel.write(buffer);
Pipe.SourceChannel sourceChannel = pipe.source(); buffer.flip(); int len = sourceChannel.read(buffer); System.out.println(new String(buffer.array(), 0, len));
sourceChannel.close(); sinkChannel.close(); }
|