Netty框架

NIO入门

2018-06-09  本文已影响4人  z七夜

写在前面

Java NIO(New IO) 是从JDK1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API,NIO与原来的IO有相同的作用和目的,但是使用的方法完全不同,NIO支持面向缓冲区,基于通道的IO操作,NIO将以更高的方式进行文件的读写操作。

1.传统IO与NIO的区别

image.png

1.1传统IO

传统IO面向流,当程序与文件建立链接之后,通过操作字节数组来进行读写(read,write)字节流,

image.png

1.2 NIO

NIO面向缓冲区,基于通道进行数据传输,当文件与程序建立通道之后,数据存储在缓冲区中,进行运输,缓冲区是双向的,可以来回走,通道就好比火车道,缓冲区就好比火车,程序和文件相当于两个车站,挡在某个车站接了人,运到另一个车站,还可以接着接人,在回来

image.png

2.NIO入门

NIO系统核心在于:通道(Channel)和缓冲区(Buffer),选择器(Selector),通道表示打开到IO设备(文件,套接字(Socket))的链接,若需要使用NIO系统,需要获取用于链接Io设备的通道以及容纳数据的缓冲区,然后操作缓冲区,对数据进行处理

2.1 缓冲区(Buffer)

2.1.1 常用数据类型的缓冲区

缓冲区负责数据的存取,底层使用数组实现的,用于存储不同类型的数据

ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer

2.1.2 缓冲区的方法

put():存放数据
get():获取数据
wrap(char[] arras):用自己的数组用作缓冲区的备份存储器

2.1.3 核心属性

所有的缓冲区都继承Buffer类


image.png

private int mark = -1; 标记当前操作数据的位置,使用reset方法可以返回这个位置
private int position = 0; 表示当前操作数据的位置
private int limit; 界限,表示缓冲区中可以操作数据的量(limit后面的数据不可以操作)
private int capacity;表示缓冲区的容量,一旦确定不能改变

通过实例看一下:

image.png

代码:


        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("----put()方法");
        byteBuffer.put("abcde".getBytes());
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("----flip()方法");
        byteBuffer.flip();
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("----get()方法");
        byte[] dst = new byte[byteBuffer.limit()];
        byteBuffer.get(dst);
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("---rewind()方法,重读");
        byteBuffer.rewind();
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("----第二次get()方法");
        byte[] dst1 = new byte[byteBuffer.limit()];
        byteBuffer.get(dst1);
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

        System.out.println("-----clear方法,清空缓冲区");
        byteBuffer.clear();
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());

效果:


image.png

2.1.4 获取缓冲区的方法

四、直接缓冲区与非直接缓冲区
非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM内存中
直接缓冲区:通过allocateDirect()方法分配缓冲区,缓冲区建立在操作系统的物理内存中

操作:

 ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        byteBuffer.put("abcdefg".getBytes());
        byteBuffer.flip();
        byte[] dst = new byte[byteBuffer.limit()];
        byteBuffer.get(dst,0,2);

        System.out.println(new String(dst,0,2));
        System.out.println(byteBuffer.position());
        byteBuffer.mark();//标记一下当前的position的位置


        byteBuffer.get(dst,2,2);
        System.out.println(new String(dst,2,2));
        System.out.println(byteBuffer.position());

        byteBuffer.reset();//恢复mark的位置
        System.out.println(byteBuffer.position());

效果:


image.png

mark之后,调用reset方法,position会回到mark的位置,重新读

2.2 通道

通道用于源节点与目标节点的连接,在JavaNIO中负责缓冲区中的数据的传输

2.2.1通道的主要实现类

image.png

2.2.2 获取通道的办法

image.png


使用getChannel方法
    @Test
    public void test1() {

        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inputStream = new FileInputStream("1.txt");
            outputStream = new FileOutputStream("2.txt");

            //1.获取通道
            inChannel = inputStream.getChannel();
            outChannel = outputStream.getChannel();

            //2.分配缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            //3.将通道中的数据写入缓冲区,将缓冲区的数据读出来写入通道
            while (inChannel.read(byteBuffer) != -1) {
                //将缓冲区的数据写入通道
                byteBuffer.flip();
                outChannel.write(byteBuffer);
                byteBuffer.clear();

            }
        } 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();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

使用open方法

 @Test
    public void test2() throws IOException {

        //得到通道
        FileChannel inChannel = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("3.txt"), StandardOpenOption.WRITE,
                StandardOpenOption.READ, StandardOpenOption.CREATE);

        //2.创建内存映射文件
        MappedByteBuffer inMapper = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer outMapper = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

        //直接对缓冲区中的数据进行操作
        byte[] dst = new byte[inMapper.limit()];

        inMapper.get(dst);
        outMapper.put(dst);

        inChannel.close();
        outChannel.close();


    }

2.3 阻塞与非阻塞

观看下一篇https://www.jianshu.com/p/dbe9b22d695e

QQ群:552113611

上一篇下一篇

猜你喜欢

热点阅读