java的io操作

    科技2022-08-12  109

    最近在做一个日志组件,考虑到性能和日志的完整性,使用了MMAP,即内存映射的方式写日志,顺便总结一下Java里面的IO操作.

    1.IO

    IO是阻塞性的,效率不高,但是很容易理解 可以想像成是一个水管,水管里面有空位才能往里写,否则就要等待, 水管里面有水才能读,否则也只能等待.不管IO怎么包装,其操作都是针对字节的.

    private static void testIO()throws Exception{ File file = new File("test.txt"); //写 FileOutputStream fileOutputStream = new FileOutputStream(file); byte[] bytes = "hello world".getBytes(); fileOutputStream.write(bytes); fileOutputStream.close(); //读 FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[1024]; fileInputStream.read(buffer); fileInputStream.close(); }

    2.NIO

    NIO的操作是针对buffer的,且是非阻塞的,因此效率要比IO高. 其中的核心是selector , 一个selector可以监听多个channel , 当每个channel当中有事件产生时, 便会出发selector的事件

    //服务端 private static void testNIO_Server() throws Exception{ Selector selector = Selector.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress("127.0.0.1",8000)); serverSocketChannel.configureBlocking(false).register(selector, SelectionKey.OP_ACCEPT); ByteBuffer readBuff = ByteBuffer.allocate(1024); ByteBuffer writeBuff = ByteBuffer.allocate(1024); writeBuff.put("recived it !".getBytes()); writeBuff.flip(); while(true){ int nReady = selector.select(); if(nReady <= 0){ continue; } Set<SelectionKey> keys = selector.selectedKeys(); Iterator iterator = keys.iterator(); while(iterator.hasNext()){ SelectionKey selectionKey = (SelectionKey) iterator.next(); iterator.remove(); if(selectionKey.isAcceptable()){ //创建新的连接,并监听read和write事件 SocketChannel socketChannel= serverSocketChannel.accept(); socketChannel.configureBlocking(false).register(selector,SelectionKey.OP_READ); }else if(selectionKey.isReadable()){ //read事件 readBuff.clear(); SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); socketChannel.read(readBuff); readBuff.flip(); System.out.println("服务端收到的:"+new String(readBuff.array())); selectionKey.interestOps(SelectionKey.OP_WRITE); }else if(selectionKey.isWritable()){ //write事件 SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); socketChannel.write(writeBuff); selectionKey.interestOps(SelectionKey.OP_READ); } } } } //客户端 private static void testNIO_Client()throws Exception{ ByteBuffer writeBuffer = ByteBuffer.allocate(128); writeBuffer.put("hello".getBytes()); writeBuffer.flip(); SocketChannel ssc = SocketChannel.open(); boolean connectResult = ssc.connect(new InetSocketAddress("127.0.0.1",8000)); ssc.write(writeBuffer); }

    3.MMAP

    MMAP是内存映射,将磁盘上的空间映射到内存当中,性能接近于直接写内存,而且由系统保证能将内存当中的内容写入到磁盘. MMAP需要事先指定大小,然后往里面进行读写操作.

    public static void testMMAP() throws Exception{ File mmapFile = new File("test.txt"); MappedByteBuffer mappedByteBuffer = new RandomAccessFile(mmapFile.getAbsolutePath(), "rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, mmapFile.length()); byte[] bytes = "hello world".getBytes(); mappedByteBuffer.put(bytes); }
    Processed: 0.014, SQL: 9