java NIO实现文件复制

1 篇文章 0 订阅
传统IO
面向字节
流(类比水流)

NIO: new IO  javaNIO核心在于 通道和缓冲区,先获取通道,然后操作缓冲区,对数据进行处理
通道Channel(类比铁路,仅仅用于连接,不能传输数据)
缓冲区Buffer(类比火车,双向)
特点:
面向缓冲区
非阻塞

Buffer 缓冲区
四个核心属性:
capacity: 容量,表示缓冲区中最大存储数据的容量,不能改变
limit: 界限,表示缓冲区可以操作数据的大小,limit 后数据不能进行读写
position: 位置,表示缓冲区正在操作的位置
mark:标记,表示记录当前position的位置,可以通过reset()恢复position的位置(没那么重要,只要知道是辅助mark()、reset()操作的就行了)
0<=mark<=position <= limit <= capacity(这个不用记,理解即可)
核心方法:
    ByteBuffer.allocate();//获取缓冲区
    put();//出入数据到缓冲区
    get();//获取缓冲区数据
    flip();//切换读模式,下面的两个操作不用记,理解即可
        limit = position;
        position = 0;
    rewind();//重新读
        position =0;
    clear();//清空缓冲区
        limit =capacity;
        position =0;
    mark();//表示记录当前position的位置,可以通过reset()恢复mark的位置
    reset();//恢复到mark位置

非直接缓冲区:通过allocate()方法分配的缓冲区,将缓冲区建立在JVM内存中
直接缓冲区 allocateDirect()方法分配的缓冲区,将缓冲区建立在物理内存中
    直接缓冲区可以提升性能,但是不要滥用,建议有明显好处时使用这个,放入直接缓冲区中。


通道Channel:负责缓冲区数据的传输
    FileChannel   文件的通道
    SocketChannel  网络socket通道
    ServerSocketChannel
    DatagramChannel

获取通道:
    很多类中提供getChannel()方法获取通道
    本地IO:
    FileInputStream/FileOutputStream
    RandomAccessFile
    网络IO:
    Socket
    ServerSocket
    DatagramSocket

    各个通道类有open()静态方法,获取通道
    Files工具类有newByteChannel()
通道的方法:
    finChannel.read(buf) //把通道的数据写入缓冲区中
    foutChannel.write(buf);//把缓冲区的数据读入通道中

    channel.read(bufs[]) // 分散读取 将通道的数据分散到多个缓冲区中
    channel.write(bufs[]) //聚集写入 将多个缓冲区中的数据聚集到通道中

//通道之间的传输
    transferFrom();// 将通道的数据 复制到 另外一个通道中
    transferTo();// 从另外的通道获取数据

 

copy文件:

写法1:

 /**
     * 利用缓冲区复制文件
     */
    public static void copyFile(){
        FileInputStream fin = null;
        FileOutputStream fout = null;
        FileChannel finChannel = null;
        FileChannel foutChannel = null;
        try {
            fin = new FileInputStream("testFile/test.txt");
            fout = new FileOutputStream("testFile/test_copy.txt");
            finChannel = fin.getChannel();
            foutChannel = fout.getChannel();
            //缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);

            //将通道中的数据存入缓冲区
            while (finChannel.read(buf) != -1){
                buf.flip();//切换到读模式
                //将缓缓从去的数据写入通道
                foutChannel.write(buf);
                buf.clear();//缓冲区重置
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭通道和流
            if(finChannel != null){
                try {
                    finChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(foutChannel != null){
                try {
                    foutChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fout != null){
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fin != null){
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

写法2(异常处理已忽略,仅做示例用):

 /**
     * 利用缓冲区复制文件  直接抛出异常
     */
    public static void copyFile_channelCopy() throws Exception {
        FileInputStream fin = null;
        FileOutputStream fout = null;
        FileChannel finChannel = null;
        FileChannel foutChannel = null;
        fin = new FileInputStream("testFile/test.txt");
        fout = new FileOutputStream("testFile/test_channel_copy_2.txt");
        finChannel = fin.getChannel();
        foutChannel = fout.getChannel();

        //直接把通道进行数据传输
        // transferTo 和 transferFrom两者选1即可
//        finChannel.transferTo(0,finChannel.size(),foutChannel);
        foutChannel.transferFrom(finChannel,0,finChannel.size());
        //正式写法是需要写在 try-catch-finally 中的,处理仅作为学习
        finChannel.close();
        foutChannel.close();
        fin.close();
        fout.close();

    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值