Java NIO之通道Channel代码实例


相关Java NIO详解: Java NIO详解

代码实例



import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 通道channel:
 * 用于源节点与目标节点的连接,本身不负责存储数据,主要是配合缓冲区,负责数据的运输。
 * 1.主要的实现类:
 *      java.nio.channels.Channel接口
 *          --用于本地文件:
 *              -FileChannel
 *          --用于网络
 *              -SocketChannel一般用于客户端,TCP协议
 *              -ServerSocketChannel一般用于服务端,TCP协议
 *              -DatagramChannel基于UDP协议,主要用于发送和接收数据包
 * 2.获取通道Channel的方法
 * (1)java针对支持通道的类提供了getChannel()方法
 *      --本地文件
 *      FileInputStream/FileOutoutStream
 *      RandomAccessFile
 *      --网络传输
 *      Socket
 *      ServerSocket
 *      DatagramSocket
 *  (2)在JDK1.7中的NIO2针对各个通道提供了静态方法open()
 *  (3)在JDK1.7中的NIO2中Files工具类newByteChannel()
 * 3.通道之间的传输,两种方法
 * transferForm()
 * transferTo()
 *
 */
public class ChannelDome {

    /**
     *    main测试,利用线程池进行创建线程并运行。
     */

    public static void main(String[] args)  {
        //1.创建可重用固定线程数量的线程池
        ExecutorService executorService= Executors.newFixedThreadPool(10);
        //System.out.println(executorService.getClass());//查看调用了那个接口的对应实现类。
        //2.执行指定的线程的操作,需要提供的是Runnable接口或Callable接口实现类的对象
        copyFileThread1 thread1=new copyFileThread1();
        copyFileThread2 thread2=new copyFileThread2();
        channelWriteAndRead thread3=new channelWriteAndRead();
        channelTransfer thread4=new channelTransfer();
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        executorService.execute(thread4);
        //executorService.submit();
        executorService.shutdown();

    }
    /**
     * 1.利用通道进行本地文件的复制功能(非直接缓冲区)
     * @param copyFrom
     * @param copyTo
     * @return boolean
     */
    public boolean copyFileByChannel(String copyFrom,String copyTo) throws IOException {
        long start=System.currentTimeMillis();
        boolean result=false;
        FileInputStream inputStream=null;
        FileOutputStream outputStream=null;
        FileChannel inputChannel=null;
        FileChannel outputChannel=null;
        try {
            //1.获取本地输入输出流
            inputStream = new FileInputStream(copyFrom);
            outputStream = new FileOutputStream(copyTo);

            //2.获取本地对应输入输出通道
            inputChannel = inputStream.getChannel();
            outputChannel = outputStream.getChannel();

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

            //4.将输入通道中的数据存入缓冲区
            while (inputChannel.read(byteBuffer) != -1) {//从当前通道position读取数据到缓冲区,若到达末尾,返回-1
                byteBuffer.flip();//切换到读取数据模式
                //5.将缓冲区的数据写入到输出通道中
                outputChannel.write(byteBuffer);
                byteBuffer.clear();//清空缓冲区
                result=true;
            }

        }finally {
            if(inputStream !=null){
                inputStream.close();
            }
            if(inputChannel !=null){
                inputChannel.close();
            }
            if(outputChannel !=null){
                outputChannel.close();
            }
            if(outputStream !=null){
                outputStream.close();
            }
        }
        long end=System.currentTimeMillis();
        System.out.println("非缓冲区复制文件耗时:"+(end-start));
        return  result;
    }

    /**
     * 2.利用通道进行本地文件的复制功能(直接缓冲区,利用内存映射文件)
     * @param  copyFrom
     * @param  copyTo
     * @return boolean
     */
    public boolean copyFileByChannel2Direct(String copyFrom,String copyTo) throws IOException {
        long start=System.currentTimeMillis();
        //1.获取输入输出通道
        FileChannel inputChannel= FileChannel.open(Paths.get(copyFrom), StandardOpenOption.READ);
        FileChannel outputChannel=FileChannel.open(Paths.get(copyTo),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);
        //2.获取内存映射文件
        MappedByteBuffer inMappedBuf=inputChannel.map(FileChannel.MapMode.READ_ONLY,0,inputChannel.size());
        MappedByteBuffer outMappedBuf=outputChannel.map(FileChannel.MapMode.READ_WRITE,0,inputChannel.size());
        //3.直接对缓冲区进行读写操作
        byte[] dst=new byte[inMappedBuf.limit()];
        inMappedBuf.get(dst);
        outMappedBuf.put(dst);
        //4.关闭输入输出通道
        inputChannel.close();
        outputChannel.close();
        long end =System.currentTimeMillis();
        System.out.println("直接缓冲区复制的耗时:"+(end-start));
        return true;
    }

    /**
     * 3.通道之间的数据传输(直接缓冲区)
     * @param  copyFrom
     * @param copyTo
     * @return boolean
     */
    public boolean copyFileByChannel2Transfer(String copyFrom,String copyTo) throws IOException {
        FileChannel inChannel=FileChannel.open(Paths.get(copyFrom),StandardOpenOption.READ);
        FileChannel outChannel=FileChannel.open(Paths.get(copyTo),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);
        //1.将通道中的字节数据传输到指定通道,transferTo()
        inChannel.transferTo(0,inChannel.size(),outChannel);
        //2.从指定通道中获取自己数据到通道中,transferFrom()
        //outChannel.transferFrom(inChannel,0,inChannel.size());
        return true;
    }

    /**
     * 4.通道的分散和聚合
     *分散读取:将通道的数据读取到多个缓冲区Bufer中
     * 聚集写入:将多个缓冲区的数据聚集写到通道Channel中
     * @param writeFlie
     * @param readFlie
     */
    public void channelWriteAndRead(String writeFlie,String readFlie) throws IOException {
        //1.读取指定文件
        RandomAccessFile randomAccessFile=new RandomAccessFile(readFlie,"rw");
        //2.获取本地文件通道
        FileChannel fileChannel=randomAccessFile.getChannel();

        //3.分配指定大小的缓冲区
        ByteBuffer buf1=ByteBuffer.allocate(1024);//设置多大就缓存多大
        ByteBuffer buf2=ByteBuffer.allocate(1024);
        //4.分散读取
        ByteBuffer[] bufs={buf1,buf2};
        fileChannel.read(bufs);

        for(ByteBuffer byteBuffer:bufs){
            byteBuffer.flip();
            System.out.println("每个缓冲区的数据如下:");
            System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));

        }
        //5.聚集写入(指定文件)
        RandomAccessFile randomAccessFile1=new RandomAccessFile(writeFlie,"rw");//指定写到那个文件下
        FileChannel fileChannel1=randomAccessFile1.getChannel();
        fileChannel1.write(bufs);
    }


}

//创建线程1测试,非缓冲区文件复制
class copyFileThread1 implements Runnable{
    ChannelDome channelDome=new ChannelDome();
    String copyFrom="G:\\copyFromFile\\copyForm.log";
    String copyTo="H:\\copyToFile\\NoDirect\\copyTo1.log";
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread() +"当前线程正在执行利用非缓冲区本地文件复制功能");
            channelDome.copyFileByChannel(copyFrom,copyTo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//创建线程2测试,
class copyFileThread2 implements Runnable{
    ChannelDome channelDome =new ChannelDome();
    String copyFrom="G:\\copyFromFile\\copyForm.log";
    String copyTo="H:\\copyToFile\\Direct\\copyTo2.log";
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread() +"当前线程正在执行利用缓冲区本地文件复制功能");
            channelDome.copyFileByChannel2Direct(copyFrom,copyTo);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//通道的分散读取和聚集写入线程测试
class channelWriteAndRead implements Runnable{

    ChannelDome channelDome=new ChannelDome();
    String writeFile="G:\\copyFromFile\\copyForm.log";
    String readFile="H:\\copyToFile\\Read\\read.log";

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread() +"当前线程正在执行通道的分散读取和聚集写入线程功能");
            channelDome.channelWriteAndRead(readFile,writeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//通道之间的传输线程测试
class channelTransfer implements Runnable{
    ChannelDome channelDome=new ChannelDome();
    String copyForm="G:\\copyFromFile\\copyForm.log";
    String copyTo="H:\\copyToFile\\transfer\\transfer.log";
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread() +"当前线程正在执行通道之间的传输线程功能");
            channelDome.copyFileByChannel2Transfer(copyForm,copyTo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

控制台输出结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值