NIO学习笔记(三)——NIO复制文件

前面我们已经学习了NIO的两大核心组件,channel和buffer。现在我们继续利用NIO来完成文件的复制操作。复制文件的步骤上与之前读取文件的步骤其实没有太大的区别,只不过使用了一套新的API而已。如下:

/**
 * 利用NIO进行文件复制
 */
public class NIOFileCopy {
    public static void main(String[] args) {
        //创建文件读取通道

        //创建文件写入通道

        //读取到buffer

        //写入到目标通道
    }
}

接下来我们就把这部分程序来完成。首先创建读取文件通道:

//创建读取文件通道以及写入文件通道
try (FileChannel srcChannel = FileChannel.open(Paths.get("f:/test.txt"), StandardOpenOption.READ);
    FileChannel targetChannel = FileChannel.open(Paths.get("f:/test1.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
    /* do... */
}

这里大家一定要习惯这个思路,在NIO这一部分,很多的内容都是通过静态的方法来创建对象的。读取文件通道的option的枚举类型为READ,同时在这里声明目标文件通道,同样的利用Paths.get方法声明文件路径。目标文件通道的option的枚举类型我们需要注意一下,如果目标文件不存在的话,单单一个WRITE是没办法把文件创建出来的,所以我们需要在这里追加一个参数——CREATE。open的option是一个可变长的参数,也就是说后面我们可以追加很多个StandardOpenOption参数设置,这里我们就为它设置了两个参数:WRITE和CREATE。

现在两个通道我们都创建完毕了,接着我们把目标读取到buffer当中去:

//读取到buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
int flag = srcChannel.read(buffer);
while(-1 != flag) {
    //切换写模式到读模式 -> limit = position -> position = 0
    buffer.flip(); 
    while(buffer.remaining()) {
        /* do... */
    }
    buffer.clear();
    flag = srcChannel.read(buffer);
}

读取至buffer的框架我们已经完成了,那么while循环里就可以进行写入到目标通道的工作了。上一节我们学习到,读取是通过buffer.get方法逐字节按position取,或者是我们直接通过buffer.array方法也能把byte数组取出来。不难想到,与读取相对应的就有一个buffer.put方法来写入。但我们如果进行文件复制,其实并不需要这么复杂。因为srcChannel和targetChannel可以公用这个buffer,我从srcChannel读出buffer,同样这个buffer也可以被用于写入targetChannel。这也是它比输入输出流的思想要先进,封装的想法也更加完善。如下:

while(-1 != flag) {
    buffer.flip(); 

    //写入到目标通道
    int result = targetChannel.write(buffer);
    System.out.println(result);

    buffer.clear();
    flag = srcChannel.read(buffer);
}

这样我们就成功实现了对一个文件的复制,完整代码如下:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 利用NIO完成文件复制。
 * @author 青葉
 *
 */
public class NIOFileCopy {
    public static void main(String[] args) {
        //创建读取文件通道
        //创建写入文件通道
        try(FileChannel srcChannel = FileChannel.open(Paths.get("f:/test.txt"), StandardOpenOption.READ);) {
            FileChannel targetChannel = FileChannel.open(
                    Paths.get("f:/test1.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            //读取到buffer
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int flag = srcChannel.read(buffer);
            while(-1 != flag) {
                buffer.flip(); //切换写模式到读模式 -> limit = position -> position = 0
                //写入到目标通道
                int result = targetChannel.write(buffer);
                System.out.println(result);
                buffer.clear();
                flag = srcChannel.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

其实JDK1.7之后,还有两种方式可以创建FileChannel,在这里也顺带提一下。其中第二种方法很好的诠释了传统IO到NIO的过渡,如下:

//通过Files工具类创建channel
FileChannel channel = Files.newByteChannel(path, options); 
//通过Channels工具类,创建channel对象
Channels.newChannel(inputstream);

说到这里,这个Files类,它不单单可以创建channel,还有更加好用的一些方法。比如说我们这节介绍的文件复制的动作,其实在Files中,有一个方法可以直接完成这个动作——copy方法。它提供了3种重载,参数种类如下:

(1)2个路径 + 1个配置参数
(2)1个路径 + 1个输出流
(3)1个输入流 + 1个路径

可以通过多种重载方式来完成这个文件复制操作,所以我们其实可以用一行代码完成上面所有代码完成的事情,如下:

Files.copy(Paths.get("f:/test.txt"), Paths.get("f:/test1.txt"), StandardCopyOption.REPLACE_EXISTING);

更多文件复制这一块的内容及细节大家可以通过阅读API来细细体会。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值