二、NIO

NIO

在这里插入图片描述

简介

NIO支持面向缓冲区的、支持通道的IO操作。NIO将以更加高校的方式进行文件的读写操作。

NIO和传统IO区别

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
通道就理解成铁路,配合缓冲区才能完成数据传输,负责连接。 传输还是要靠缓冲区,可以理解成火车。

  • 流是单向的,缓冲区是双向的。

  • IO面向流,NIO面向缓冲区

通道和缓冲区

在这里插入图片描述

缓冲区

一、缓冲区(Buffer):在Java NIO负责数据的存取,缓冲区就是数组,用于存储不同类型的数据。

根据数据类型不同(Boolean 除外),提供了相应类型的缓冲区。

  • ByteBuffer
  • CharBuffer
  • IntBuffer
  • ShortBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

上述的缓冲区的管理方式一致,都是通过allocate()获取一个缓冲区

二、缓冲区存取数据的两个核心方法:

  • put() :存入数据到缓冲区。
  • get() : 获取缓冲区中的数据。
缓冲区中的四个核心属性
  • capacity:容量,表示缓冲区中最大存储数据的容量,一旦声明不能改变
  • limit:界限,标示缓冲区中可以操作数据的大小,limit后面的数据是不能进行读写的。
  • position:表示缓冲区中正在操作数据的位置
    position <= limit <= capacity
  • mark : 标记,表示记录当前position的位置,可以通过reset()将position恢复到mark的位置,buf.mark();这样的话就记录了position位置
import java.nio.ByteBuffer;

/**
 * 一、缓冲区(Buffer):在Java NIO负责数据的存取,缓冲区就是数组,用于存储不同类型的数据。
 *
 * 根据数据类型不同(Boolean 除外),提供了相应类型的缓冲区。
 * ByteBuffer
 * CharBuffer
 * IntBuffer
 * ShortBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 *  上述的缓冲区的管理方式一致,都是通过allocate获取一个缓冲区。
 */
public class TestBuffer
{
    public static void main(String[] args)
    {
        ByteBuffer buf = ByteBuffer.allocate(1024);
        System.out.println("----------allocate()-----------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println("----------put()-----------------");
        String ss = "abcde";
        buf.put(ss.getBytes());
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println("----------flip()-----------------");
        buf.flip();
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println("----------get()-----------------");
        byte[] dst = new byte[buf.limit()];
        buf.get(dst);
        System.out.println(new String(dst,0,dst.length));
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println("----------rewind()------------");
        buf.rewind(); //可以重复读取数据
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println("----------clear()------------");
        //数据还存在,但是不知道limit到哪里了。
        buf.clear(); //清空缓冲区,但是缓冲区中的数据依然存在,但是处于"被遗忘"状态。

        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println((char) buf.get(0));
    }

}

输出结果为

----------allocate()-----------------
0
1024
1024
----------put()-----------------
5
1024
1024
----------flip()-----------------
0
5
1024
----------get()-----------------
abcde
5
5
1024
----------rewind()------------
0
5
1024
----------clear()------------
0
1024
1024
a
flip()

在这里插入图片描述
flip()之后,position和limit会发生变化。

直接缓冲区与非直接缓冲区

非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中。
直接缓冲区:通过allocateDirect()方法分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以通过buffer.isDirect()来判断是直接缓冲区还是非直接缓冲区。

通道

通道:由java.io.channels包定义的。Channel表示IO源与目标打开的连接。
Channel类似于传统的“流”。只不过Channel本身不能直接访问数据,Channel只能与Buffer进行交互。

在这里插入图片描述
DMA(Direct Memory Access,直接存储器访问) 。

他的作用就是不需要经过CPU进行数据传输,也就是替CPU分担点事情做,什么事情?数据传输方面的事情。也就是说,你只要使能并配置好了DMA,DMA就可以将一批数据从源地址搬运到目的地址去而不经过CPU的干预,这样可以为CPU节省好多精力去干更重要的事情很人性化。就像我们人一样,我们平常习惯性的动作是不用经过大脑思考的,比如说眨眼睛,呼吸等。DMA就是负责这些工作的,但它没人这么智能,需要将它设置好了它才会正常工作。

通道的主要的实现类

一、通道

  • 用于源结点和目标结点的连接,在Java NIO中负责缓冲区数据的传输,Channel本身不存储数据,因此需要缓冲区进行配合

二、通道的主要实现类
java.nio.channels.Channel 接口:

  • FileChannel
  • SocketChannel (TCP)
  • ServerSocketChannel (TCP)
  • DatagramChannel(UDP)

三、获取通道

  • 1、Java针对支持通道的类提供了getChannel()方法,下面的这些类都有getChannel()方法获取对应的通道
    本地IO:
    FileInputStream/FIleOutputStream
    RandomAccessFile
    网络IO:
    Socket
    ServerSocket
    DatagramSocket

  • 2、在JDK1.7中的NIO2 针对各个通道提供了open()获取各个通道。

  • 3、JDK1.7中的NIO2 的Files工具类的newByteChannel()方法

利用通道完成文件的复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class TestChannel
{
    public static void main(String[] args) throws IOException
    {
        FileInputStream fileInputStream = new FileInputStream("1.jpg");
        FileOutputStream fileOutputStream = new FileOutputStream("1.jpg");

        //获取通道
        FileChannel inChannel = fileInputStream.getChannel();
        FileChannel outChannel = fileOutputStream.getChannel();

        //分配指定大小的缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        //将通道中管的数据存入缓冲区
        while(inChannel.read(byteBuffer)!=-1)
        {

            byteBuffer.flip(); //切换成读取数据的模式
            //将缓冲区中的数据写入通道
            outChannel.write(byteBuffer);
            byteBuffer.clear();
        }
        inChannel.close();
        outChannel.close();
        fileInputStream.close();
        fileOutputStream.close();


    }
}

使用直接缓冲区完成文件的复制(内存映射文件)

在这里插入图片描述

通道之间的文件船速

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值