java中的nio
来源:互联网 发布:淘宝淘金币领取 编辑:程序博客网 时间:2024/06/06 07:39
1.什么是nio
nio是一个非阻塞的IO。之前学的IO是面向流的一种技术。而nio是面向缓冲区的一种技术。采用通道传输。nio可以高效的进行文件的读写操作(之所以速度的提高来自于操作系统所执行的IO方式:缓冲区和通道)。
2.缓冲区
缓冲区的API除了没有boolean对应的Buffer,其他基本类型都有,如IntBuffer,ByteBuffer,FloatBuffer等。
缓冲区的原理:
缓冲区在java nio中负责数据的存取。缓冲区就是数组,用于存取不同类型的数据。
缓冲区的属性:
初始化图:(分配空间为7的容量)
capacity:容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
limit:界限,表示缓冲区中可以操作数据的大小。(limit后数据不能读写)
position:位置,表示缓冲区中正在操作数据的位置。
public class TestBuffer {private void printProperties(int position,int limit,int capacity){System.out.println("capacity:"+capacity);System.out.println("limit:"+limit);System.out.println("position:"+position);} @Test public void test1(){ String str ="abcde"; //分配一个指定大小的缓冲区 ByteBuffer buf =ByteBuffer.allocate(1024); System.out.println("----------初始化------------"); printProperties(buf.position(),buf.limit(),buf.capacity()); }}结果:
put方法:存入元素到缓冲区
System.out.println("-----------put------------");buf.put(str.getBytes());printProperties(buf.position(),buf.limit(),buf.capacity());结果:
flip方法:用来切换到读模式
buf.flip();printProperties(buf.position(),buf.limit(),buf.capacity());System.out.println("----------get-------------");byte[] dest =new byte[buf.limit()];buf.get(dest);printProperties(buf.position(),buf.limit(),buf.capacity());结果:
rewind方法:重复读,将位置设置为零并丢弃标记。
System.out.println("----------rewind-------------");buf.rewind();printProperties(buf.position(),buf.limit(),buf.capacity());结果:
clear方法:清空缓冲区,将位置设置为零,限制设置为该容量,并且丢弃标记。
System.out.println("----------clear-------------");buf.clear();printProperties(buf.position(),buf.limit(),buf.capacity());结果:
mark和reset方法:
mark属性:标记,表示记录当前position的位置。可以通过reset()恢复到mark的位置。reset 恢复到mark标记的位置。
@Testpublic void test2(){String str ="efghijk";ByteBuffer buf =ByteBuffer.allocate(1024);printProperties(buf.position(), buf.limit(), buf.capacity());buf.put(str.getBytes());buf.flip();byte[] dest =new byte[buf.limit()];buf.get(dest,0,3);System.out.println(new String(dest,0,2));System.out.println(buf.position());//markbuf.mark();buf.get(dest,2,2);System.out.println(new String(dest,2,2));System.out.println(buf.position());//reset 恢复到mark标记的位置buf.reset();System.out.println(buf.position());}结果:
直接缓冲区与间接缓冲区的区别:
间接缓冲区:通过allocate方法分配缓冲区,将缓冲区建立在jvm内存中
直接缓冲区:通过allocateDirect方法分配直接缓冲区,将缓冲区建立在操作系统的物理内存中。
3.通道
通道在java nio中负责缓冲区中数据的传输。
主要实现类:
①FileChannel:用于操作本地的通道。
②SocketChannel:用于操作网络TCP协议的通道。
③ServerSocketChannel:用于操作网络TCP协议的通道。
④DatagramChannel:用于操作网络UDP协议的通道。
获取通道:
本地IO方式:FileInputStream/FileOutputStream、RandomAccessFile
网络IO方式:Socket、ServerSocket、DatagramSocket
示例:
方式一:使用文件流来获取通道的方式来复制文件
@Testpublic void testChannel() throws Exception{FileInputStream fis =new FileInputStream("C:\\Users\\Administrator\\Desktop\\触发器.txt");FileOutputStream fos =new FileOutputStream("C:\\Users\\Administrator\\Desktop\\触发器1.txt");FileChannel fic =fis.getChannel();FileChannel foc =fos.getChannel();ByteBuffer buf =ByteBuffer.allocate(1024);while(fic.read(buf) !=-1){buf.flip();foc.write(buf);buf.clear();}foc.close();fic.close();fos.close();fis.close();}结果:
方式二:将文件区域直接映射到内存中来创建
@Testpublic void testChannelByOpen() throws Exception{FileChannel inChannel =FileChannel.open(Paths.get("C:\\Users\\Administrator\\Desktop\\触发器.txt"), StandardOpenOption.READ);FileChannel outChannel =FileChannel.open(Paths.get("C:\\Users\\Administrator\\Desktop\\触发器2.txt"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);//直接字节缓冲区,其内容是文件的内存映射区域:将此通道的文件区域直接映射到内存中。MappedByteBuffer inMappedBuf =inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());MappedByteBuffer outMapperBuf =outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());//直接对缓冲区进行读写操作byte[] dest =new byte[inMappedBuf.limit()];inMappedBuf.get(dest);outMapperBuf.put(dest);outChannel.close();inChannel.close();}结果:
4.字符编码与解码
示例:
@Testpublic void testCharset() throws IOException{Charset cs1 =Charset.forName("UTF-8");//获取编码器 CharsetEncoder ce =cs1.newEncoder(); //获取解码器 CharsetDecoder cd =cs1.newDecoder();CharBuffer cBuf =CharBuffer.allocate(1024);cBuf.put("张无忌");cBuf.flip();//编码ByteBuffer eBuf =ce.encode(cBuf);while(eBuf.hasRemaining()){System.out.println(eBuf.get());}//解码eBuf.flip();CharBuffer result =cd.decode(eBuf);System.out.println(result.toString());}结果:
5.阻塞式网络NIO
客户端发送本地文件数据:
@Testpublic void initClient() throws IOException{//获取网络NIO的通道SocketChannel socketChannel =SocketChannel.open(new InetSocketAddress("localhost", 8888));//获取本地文件对应的文件通道FileChannel inputChannel =FileChannel.open(Paths.get("C:\\Users\\Administrator\\Desktop\\1.jpg"), StandardOpenOption.READ);//分配1024大小的缓冲区ByteBuffer buf =ByteBuffer.allocate(1024);//循环读取本地文件通道中的缓冲区中的数据,写入到网络通道缓冲区中while(inputChannel.read(buf) !=-1){buf.flip();socketChannel.write(buf);buf.clear();}socketChannel.shutdownOutput();//发送成功提示int len =0;while((len =socketChannel.read(buf)) !=-1){buf.flip();System.out.println(new String(buf.array(),0,len));buf.clear();}inputChannel.close();socketChannel.close();}服务端接收数据:
@Testpublic void initServer() throws IOException{ ServerSocketChannel ssChannel =ServerSocketChannel.open(); FileChannel outChannel =FileChannel.open(Paths.get("C:\\Users\\Administrator\\Desktop\\2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE); ssChannel.bind(new InetSocketAddress(8888)); SocketChannel socketChannel =ssChannel.accept(); ByteBuffer buf =ByteBuffer.allocate(1024); while(socketChannel.read(buf) !=-1){ buf.flip(); outChannel.write(buf); buf.clear(); } buf.put("服务端接收客户端的数据成功".getBytes()); buf.flip(); socketChannel.write(buf); socketChannel.close(); outChannel.close(); ssChannel.close();}结果:
6.非阻塞网络NIO
客户端发送数据:
@Testpublic void initClient() throws IOException{SocketChannel socketChannel =SocketChannel.open(new InetSocketAddress("localhost", 8989));socketChannel.configureBlocking(false);ByteBuffer buf =ByteBuffer.allocate(1024);Scanner scanner =new Scanner(System.in);while(scanner.hasNext()){String content =scanner.next();buf.put((new Date()+" : "+content).getBytes());buf.flip();socketChannel.write(buf);buf.clear();}socketChannel.close();}服务端接收数据:
@Testpublic void initServer() throws IOException{ServerSocketChannel serverSocketChannel =ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.bind(new InetSocketAddress(8989));Selector selector =Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while(selector.select() >0){Iterator<SelectionKey> it =selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey key =it.next();if(key.isAcceptable()){SocketChannel socketChannel =serverSocketChannel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);}else if(key.isReadable()){SocketChannel socketChannel =(SocketChannel) key.channel();ByteBuffer buf =ByteBuffer.allocate(1024);int len =0;while((len =socketChannel.read(buf))>0){buf.flip();System.out.println(new String(buf.array(),0,len));buf.clear();}}it.remove();}}}结果:
7.使用UDP协议的网络NIO
服务端:
@Testpublic void server() throws IOException{DatagramChannel dc = DatagramChannel.open();dc.configureBlocking(false);dc.bind(new InetSocketAddress(9898));Selector selector = Selector.open();dc.register(selector, SelectionKey.OP_READ);while(selector.select() > 0){Iterator<SelectionKey> it = selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey sk = it.next();if(sk.isReadable()){ByteBuffer buf = ByteBuffer.allocate(1024);dc.receive(buf);buf.flip();System.out.println(new String(buf.array(), 0, buf.limit()));buf.clear();}}it.remove();}}客户端:
@Testpublic void client() throws IOException{DatagramChannel dc = DatagramChannel.open();dc.configureBlocking(false);ByteBuffer buf = ByteBuffer.allocate(1024);Scanner scan = new Scanner(System.in);while(scan.hasNext()){String str = scan.next();buf.put((new Date().toString() + " : " + str).getBytes());buf.flip();dc.send(buf, new InetSocketAddress("localhost", 9898));buf.clear();}dc.close();}结果:
- Java中的NIO问题
- Java中的NIO使用
- Java中的NIO
- java中的NIO
- Java中的NIO
- Java中的NIO
- java中的NIO
- java中的nio
- Java中的NIO
- java中的nio
- Java NIO中的缓冲区
- java中的IO与NIO
- Java NIO中的Buffer 详解
- Java中的NIO实现原理
- Java NIO中的通道Channel
- 【Java.NIO】Java NIO中的阻塞 V.S. 非阻塞
- Java NIO 详解---NIO中的异步网络IO
- Java NIO 在网络编程中的应用
- LAMP一键安装教程
- 索引(填坑进度:1%)
- dubbo+zookeeper框架出现Will not attempt to authenticate using SASL (unknown error)
- 5.divide-two-integers(两个整数相除)
- Problem & 2017.6.30
- java中的nio
- 对象转化为json
- Lua脚本:Lua调用C实现方法
- 鼠标滑过图片抖动晃动效果(css/Shake)
- Leetcode--191. Number of 1 Bits
- #5 遍历Hash对象
- 9.偏头痛杨的零基础学Java系列之集合框架入门篇
- C#Winform中窗体的美化
- Opencv 各种特征点提取和匹配