zoukankan      html  css  js  c++  java
  • 网络编程模型之NIO

    1.简单介绍

    同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

    2.模型图

    3.Buffer缓冲区

      a.Buffer在Java NIO的作用

      在Java NIO中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(Channel)服务,写入数据到通道或从通道读取数据,这样的操利用缓冲区数据来传递就可以达到对数据高效处理的目的。在NIO中主要有八种缓冲区类(其中MappedByteBuffer是专门用于内存映射的一种ByteBuffer):

      b.Buffer的属性

    容量(capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变
    上界(limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数
    位置(position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新
    标记(mark):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新一个备忘位置。调用 mark( )来设定 mark = postion。调用 reset( )设定 position =mark。标记在设定前是未定义的(undefined)。这四个属性之间总是遵循以下关系:0 <= mark <= position <= limit <= capacity

     c.Buffer的简单实例

    //Debug可以看出属性变化
    public class BufferBasic {
        public static void main(String[] args) {
            //创建一个长度为5,类型为int的buffer
            IntBuffer intBuffer=IntBuffer.allocate(5);
            //向buffer存放数据
            for (int i = 0; i < intBuffer.capacity(); i++) {
                intBuffer.put(i*2);
            }
        }
    }
    
    

      

    4.NIO通道

    java.nio.channels包中的Channel接口的已知实现类:
    FileChannel从文件中读写数据。
    DatagramChannel:能通过UDP读写网络中的数据。
    SocketChannel:能通过TCP读写网络中的数据。
    ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

     

    a.  FileChannel

    a-1. 从文件中读取信息

    /**
     * 在通道中使用buffer读数据
     */
    public class FileChannelNIO02 {
        public static void main(String[] args) throws IOException {
            //获取输入流
            File file = new File("f:\file01.txt");
            FileInputStream fileInputStream = new FileInputStream(file);
            //获取对应的channel
            FileChannel fileChannel=fileInputStream.getChannel();
            //创建缓冲区
            ByteBuffer byteBuffer=ByteBuffer.allocate((int) file.length());
            //将通道数据读取到buffer
            fileChannel.read(byteBuffer);
            //将字节转为字符串
            String str=new String(byteBuffer.array());
            System.out.println(str);
            fileInputStream.close();
    
    
        }
    }
    

     

     a-2. 写入数据到文件中

    public class FileChannelNIO {
        public static void main(String[] args) throws IOException {
            String str="dcascs";
            //创建一个输出流
            FileOutputStream  fileOutputStream=new FileOutputStream("f:\file01.txt");
            //获取对应的filechannel
            FileChannel fileChannel=fileOutputStream.getChannel();
            //创建缓冲区
            ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
            //将str放入缓冲区
            byteBuffer.put(str.getBytes());
            //对byteBuffer进行flip;
            byteBuffer.flip();
            //将bytebuffer写入到fileChannel
            fileChannel.write(byteBuffer);
            //关闭流
            fileOutputStream.close();
        }
    }
    

      

      a-3. 数据从文件中读取或者写入到文件中

    public class FileChannelNIO03 {
        public static void main(String[] args) throws IOException {
            //获取输入流
            FileInputStream fileInputStream = new FileInputStream("1.txt");
            //获取对应的channel
            FileChannel fileChannel1=fileInputStream.getChannel();
            //创建一个输出流
            FileOutputStream fileOutputStream=new FileOutputStream("2.txt");
            FileChannel fileChanne2= fileOutputStream.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(512);
            while (true){
                //重置标志位
              //  byteBuffer.clear();
                //循环读取
                int read = fileChannel1.read(byteBuffer);
                System.out.println(read);
                if (read==-1){//表示读完
                    break;
                }
                //将buffer数据写入到fileChanne2
                byteBuffer.flip();
                fileChanne2.write(byteBuffer);
            }
            fileInputStream.close();
            fileOutputStream.close();
    
    
        }
    }
    

     

     a-4. 使用transferFrom完成拷贝

    /**
     * 使用transferFrom完成拷贝
     */
    public class FileChannelNIO04 {
        public static void main(String[] args) throws IOException {
            //获取输入流
            FileInputStream fileInputStream = new FileInputStream("f:\a.jpg");
            FileChannel fileChannel1=fileInputStream.getChannel();
            //创建一个输出流
            FileOutputStream fileOutputStream=new FileOutputStream("f:\b.jpg");
            FileChannel fileChanne2= fileOutputStream.getChannel();
            //使用transferFrom完成拷贝,将a.jpg拷贝到f盘下,名字为b.jpg
            fileChanne2.transferFrom(fileChannel1,0,fileChannel1.size());
            fileChannel1.close();
            fileChanne2.close();
            fileInputStream.close();
            fileOutputStream.close();
        }
    }

     

     a-5. ReadOnlyBuffer 只读模式

    //只读
    public class ReadOnlyBuffer {
        public static void main(String[] args) {
            //创建一个长度为5,类型为int的buffer
            ByteBuffer buffer= ByteBuffer.allocate(50);
            //向buffer存放数据
            for (int i = 0; i < buffer.capacity(); i++) {
                buffer.put((byte)i);
            }
            //读取转换
            buffer.flip();
            ByteBuffer readOnly=buffer.asReadOnlyBuffer();
            System.out.println(readOnly);
            while (readOnly.hasRemaining()){
                System.out.println(readOnly.get());
            }
        }
    }
    

     a-6. MappedByteBuffer 让文件直接在内存(堆外的内存)中进行修改; 

    /**
     *  MappedByteBuffer直接在堆外内存修改,操作系统不需要拷贝一次
     */
    public class MappedByteBufferTest {
        public static void main(String[] args) throws IOException {
            /**
             * RandomAccessFile随机访问文件类
             * rw代表读写模式,不存在则新建
             */
            RandomAccessFile randomAccessFile=new RandomAccessFile("1.txt","rw");
            //获取对应的通道
            FileChannel fileChanne=randomAccessFile.getChannel();
            /**
             * 参数1:读写模式
             * 参数2:修改文件的起始位置
             * 参数3:映射到内存的大小,即文件的字节数
             */
            MappedByteBuffer map = fileChanne.map(FileChannel.MapMode.READ_WRITE, 0, 3);
            /**
             * 修改开始
             * 参数一:修改的起始位置
             * 参数二:该位置要修改成的数据
             */
            map.put(0,(byte)'H');
            randomAccessFile.close();
        }
    }
     

    未完待续...............

      

  • 相关阅读:
    Mysql数据库改名
    查看数据库大小或者表大小
    Bootstarp 水平垂直居中
    Java Collection.sort 排序升序, 降序问题
    Mysql 函数, 存储过程, 任务调度
    Mysql 日期类型 date、datetime、timestamp.
    Mysql 获取当天,昨天,本周,本月,上周,上月的起始时间
    Mysql 事件event_scheduler是OFF
    Java 文件读取
    Spring cron 定时调度配置
  • 原文地址:https://www.cnblogs.com/hyy9527/p/13058141.html
Copyright © 2011-2022 走看看