19-[BIO.NIO.AIO概述-Buffer类(缓冲区)-Channel(通道)]

学习目标

- 能够使用Junit进行单元测试
	1.在当前模块下新建lib文件夹,拷贝junit的jar包,把jar包添加到图书馆中
	2.在要执行的方法上添加一个@Test注解
	3.点击方法左边的绿色三角或者右键选择方法,选择run 方法名称运行方法
- 能够说出阻塞和非阻塞的概念
	阻塞:等待结果,什么事也不能做
	非阻塞:可以做别的事情
- 能够说出同步和异步的概念
	同步:主动获取结果
	异步:等待对方通知结果
- 能够创建和使用ByteBuffer
	获取对象的方式:
		- public static ByteBuffer allocate(int  capacity):使用一个“容量”来创建一个“间接字节缓存区”——程序的“堆”空间中创建。
        - public static ByteBuffer allocateDirect(int capacity):使用一个“容量”来创建一个“直接字节缓存区”——系统内存。
        - public static ByteBuffer wrap(byte[] byteArray):使用一个“byte[]数组”创建一个“间接字节缓存区”。
	成员方法:
		向ByteBuffer添加数据
        - public ByteBuffer put(byte b):向当前可用位置添加数据。
        - public ByteBuffer put(byte[] byteArray):向当前可用位置添加一个byte[]数组
        - public ByteBuffer put(byte[] byteArray,int offset,int len):添加一个byte[]数组的一部分
		
		- byte[] array()  获取缓冲区中包含的字节数组
		
		- int capacity() 返回此缓冲区的容量。
		
		- public int limit():获取此缓冲区的限制。
        - public Buffer limit(int newLimit):设置此缓冲区的限制。
		
		- public int position():获取当前可写入位置索引。
		- public Buffer position(int p):更改当前可写入位置索引。
		
		- public Buffer mark():设置此缓冲区的标记为当前的position位置。
		
		- public Buffer clear():还原缓冲区的状态。
          - 将position设置为:0
          - 将限制limit设置为容量capacity;
          - 丢弃标记mark。
        - public Buffer flip():缩小limit的范围。 获取读取的有效数据0到position之间的数据
          - 将limit设置为当前position位置;
          - 将当前position位置设置为0- 丢弃标记。
- 能够使用MappedByteBuffer实现高效读写
		1.创建读取文件的RandomAccessFile对象,构造方法中封装要读取的数据源和只读模式
        2.创建写入文件的RandomAccessFile对象,构造方法中封装要写入的目的地和读写模式
        3.使用读取文件的RandomAccessFile对象中的方法getChannel,获取读取文件的FileChannel
        4.使用写入文件的RandomAccessFile对象中的方法getChannel,获取写入文件的FileChannel
        5.使用读取文件的FileChannel中的方法size,获取要读取文件的大小(字节)
        6.使用读取文件的FileChannel中的方法map,创建读取文件的直接缓冲区MappedByteBuffer
        7.使用写入文件的FileChannel中的方法map,创建写入文件的直接缓冲区MappedByteBuffer
        8.创建for循环,循环size次
        9.使用读取文件的直接缓冲区MappedByteBuffer中的方法get,读取指定索引处的字节
        10.使用写入文件的直接缓冲区MappedByteBuffer中的方法put,把读取到的字节写入到指定索引处
        11.释放资源
  • 代码实现:复制2g以下的文件
package com.itheima.demo03FileChannel;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/*
    FileChannel结合MappedByteBuffer实现高效读写(重点)
    注意:
        MappedByteBuffer:直接缓冲区,最大设置缓冲区的大小为2G(2048M)
        复制的文件不能超过2g的大小,超过了就需要分块复制
    需求:
        使用MappedByteBuffer复制2g以下的文件
    实现步骤:
        1.创建读取文件的RandomAccessFile对象,构造方法中封装要读取的数据源和设置只读("r")模式
        2.创建写入文件的RandomAccessFile对象,构造方法中封装要写入的目的地和设置读写("rw")模式
        3.使用读取文件的RandomAccessFile对象中的getChannel方法,获取读取文件的FileChannel对象
        4.使用写入文件的RandomAccessFile对象中的getChannel方法,获取写入文件的FileChannel对象
        5.使用读取文件的FileChannel对象中的方法size,获取要读取的文件的大小(字节)
        6.使用读取文件的FileChannel对象中的方法map,创建读取文件的直接缓冲区MappedByteBuffer
        7.使用写入文件的FileChannel对象中的方法map,创建写入文件的直接缓冲区MappedByteBuffer
        8.创建for循环,循环size次
        9.使用读取文件的直接缓冲区MappedByteBuffer中的方法get,读取数据源指定索引出的字节
        10.使用写入文件的直接缓冲区MappedByteBuffe中的方法put,把读取到的字节写入到目的地指定的索引处
        11.释放资源
 */
public class Demo02FileChannel {
    public static void main(String[] args) throws IOException {
        long s = System.currentTimeMillis();
        //1.创建读取文件的RandomAccessFile对象,构造方法中封装要读取的数据源和设置只读("r")模式
        RandomAccessFile inRAF = new RandomAccessFile("c:\\748m.rar","r");
        //2.创建写入文件的RandomAccessFile对象,构造方法中封装要写入的目的地和设置读写("rw")模式
        RandomAccessFile outRAF = new RandomAccessFile("d:\\748m.rar","rw");
        //3.使用读取文件的RandomAccessFile对象中的getChannel方法,获取读取文件的FileChannel对象
        FileChannel inRAFChannel = inRAF.getChannel();
        //4.使用写入文件的RandomAccessFile对象中的getChannel方法,获取写入文件的FileChannel对象
        FileChannel outRAFChannel = outRAF.getChannel();
        //5.使用读取文件的FileChannel对象中的方法size,获取要读取的文件的大小(字节)
        long size = inRAFChannel.size();
        System.out.println(size);//393748024 字节
        //6.使用读取文件的FileChannel对象中的方法map,创建读取文件的直接缓冲区MappedByteBuffer
        MappedByteBuffer inMap = inRAFChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
        //7.使用写入文件的FileChannel对象中的方法map,创建写入文件的直接缓冲区MappedByteBuffer
        MappedByteBuffer outMap = outRAFChannel.map(FileChannel.MapMode.READ_WRITE, 0, size);
        //8.创建for循环,循环size次
        for (int i = 0; i < size; i++) {
            //9.使用读取文件的直接缓冲区MappedByteBuffer中的方法get,读取数据源指定索引出的字节
            byte b = inMap.get(i);
            //10.使用写入文件的直接缓冲区MappedByteBuffe中的方法put,把读取到的字节写入到目的地指定的索引处
            outMap.put(i,b);
        }
        //11.释放资源
        outRAFChannel.close();
        inRAFChannel.close();
        outRAF.close();
        inRAF.close();
        long e = System.currentTimeMillis();
        System.out.println("复制文件共耗时:"+(e-s)+"毫秒");//复制文件共耗时:2326毫秒
    }
}
  • 代码实现:复制2g以上的文件
package com.itheima.demo03FileChannel;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/*
    FileChannel结合MappedByteBuffer实现高效读写(重点)
    需求:
        使用MappedByteBuffer复制2g以上的文件
    注意:
        MappedByteBuffer:直接缓冲区,最大设置缓冲区的大小为2G(2048M)
        复制的文件不能超过2g的大小,超过了就需要分块复制
 */
public class Demo03FileChannel {
    public static void main(String[] args) throws IOException {
        long s = System.currentTimeMillis();
        //1.创建读取文件的RandomAccessFile对象,构造方法中封装要读取的数据源和设置只读("r")模式
        RandomAccessFile inRAF = new RandomAccessFile("c:\\2g.rar","r");
        //2.创建写入文件的RandomAccessFile对象,构造方法中封装要写入的目的地和设置读写("rw")模式
        RandomAccessFile outRAF = new RandomAccessFile("d:\\2g.rar","rw");
        //3.使用读取文件的RandomAccessFile对象中的getChannel方法,获取读取文件的FileChannel对象
        FileChannel inRAFChannel = inRAF.getChannel();
        //4.使用写入文件的RandomAccessFile对象中的getChannel方法,获取写入文件的FileChannel对象
        FileChannel outRAFChannel = outRAF.getChannel();
        //5.使用读取文件的FileChannel对象中的方法size,获取要读取的文件的大小(字节)
        long size = inRAFChannel.size();
        System.out.println(size);//2355126731
        //定义复制文件需要使用的变量
        long count = 1;//复制文件的的块数,默认值1
        long startIndex = 0;//复制文件的开始索引
        long copySize = size;//每次复制文件的大小,默认等于文件的总大小
        long everSize = 512*1024*1024;//分块,每块大小 512M
        //判断要复制的文件的大小是否大于每块文件的大小
        if(size>everSize){
            //计算共需要复制文件的总块数
            count = size%everSize == 0 ? size/everSize : size/everSize+1;

            //第一次复制文件的大小等于每块的大小
            copySize=everSize;
        }
        //定义一个for循环,分块就循环复制几次
        for (int i = 0; i < count; i++) {
            //6.使用读取文件的FileChannel对象中的方法map,创建读取文件的直接缓冲区MappedByteBuffer
            MappedByteBuffer inMap = inRAFChannel.map(FileChannel.MapMode.READ_ONLY, startIndex, copySize);
            //7.使用写入文件的FileChannel对象中的方法map,创建写入文件的直接缓冲区MappedByteBuffer
            MappedByteBuffer outMap = outRAFChannel.map(FileChannel.MapMode.READ_WRITE, startIndex, copySize);
            System.out.println("每块文件的开始索引:"+startIndex);
            System.out.println("每次复制文件的大小:"+copySize);
            System.out.println("--------------------------------------");
            //一读一写复制文件
            for (int j = 0; j < copySize; j++) {
                byte b = inMap.get(j);
                outMap.put(j,b);
            }
            //计算下一块复制文件的开始索引
            startIndex += copySize;
            //计算下一个复制文件的大小
            copySize = size-startIndex>everSize ? everSize : size-startIndex;
        }

        //释放资源
        outRAFChannel.close();
        inRAFChannel.close();
        outRAF.close();
        inRAF.close();
        long e = System.currentTimeMillis();
        System.out.println("复制文件共耗时:"+(e-s)+"毫秒");//复制文件共耗时:5772毫秒
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值