NIO组件之Channel

本文详细介绍了Java NIO中的FileChannel,包括如何获取、读取和写入数据,以及利用transferTo实现通道间的数据交换。此外,还讲解了Path和Files类的使用,如检查文件存在、创建目录、文件拷贝、移动、删除等操作,以及文件遍历和多级目录的处理。
摘要由CSDN通过智能技术生成

在这里插入图片描述


一、FileChannel

在这里插入图片描述

  • FileChannel只能工作在阻塞模式下

1 获取FileChannel

不能直接打开FileChannel,必须通过FileInputStream、FileOutputStream或者RandomAccessFile来获取。

  1. 通过FileInputStream获取的channel只读
  2. 通过FileOutputStream获取的channel只写
  3. 通过RandomAccessFile获取的channel根据构造器模式来决定读写

2 读取

会从channel读取数据填充道buffer。返回表示读取到了多少字节。-1表示读取到了末尾。

int readBytes=channel.read(buffer);

3 写入

写入的正确姿势如下:

ByteBuffer buffer=...;
buffer.put(...);//存入数据
buffer.flip();
while(buffer.hasRemaing){
    channel.write(buffer);
}

在while中调用channel.write是因为write不能保证一次将buffer的内容全部写入

二、通道之间的数据交换-transferTo

    public static void main(String[] args) {
        try (FileChannel from = new FileInputStream("word1.txt").getChannel();
             FileChannel to = new FileOutputStream("word3.txt").getChannel()) {
             //将channel from的数据拷贝到to里面。底层使用了零拷贝。最大限制2g。
             //超过2g使用循环解决
            long size=from.size();//表示通道的最大值
            for(long left=size;left>0;){
                //记录读取位置left
                left-=from.transferTo(size-left,left,to);
            }
        } catch (IOException e) {
        }
    }

假设有100个字节(忽略2G限制)。size=100。left=100.第一次读取。
int 50=from.transferTo(0,100,to);此时left=50。第二次读取、
int 0=from.transferTo(50,50,to),读取结束。

三、Path

jdk1.7引入了Path和Path类。

  • Path用来表示路径
  • Paths是工具类。用来获取Path实例。
  • .表示当前路径
  • …表示上一级路径
    比如目录结构如下:

D:
  |-data
    |-projects
      |-a
      |-b

        //相对路径
        Path source1 = Paths.get("1.txt");
        //绝对路径
        Path source2 = Paths.get("D:\\1.txt");
        Path source3 = Paths.get("D:/1.txt");
        //表示D:/data/projects  。路径的拼接
        Path source4 = Paths.get("D:\\data", "projects");
    Path source5 = Paths.get("D:\\data\\projects\\a\\..\\b");
    System.out.println(source5.normalize());//D:\data\projects\b

四、Files

1 检查文件是否存在

    public static void main(String[] args) {
        Path source1 = Paths.get("D:/channel/a.txt");
        System.out.println(Files.exists(source1));
    }

2 创建一级目录

 Files.createDirectory(source1);

如果目录存在,则有如下异常:

Exception in thread "main" java.nio.file.FileAlreadyExistsException

3 创建多级目录

 Files.createDirectories(path);

4 文件拷贝

        Path source1 = Paths.get("D:/channel/a.txt");
        Path source2 = Paths.get("D:/channel/b.txt");
        Files.copy(source1,source2);

如果source2存在,就会有如下异常:

Exception in thread "main" java.nio.file.FileAlreadyExistsException
Files.copy(source1,source2, StandardCopyOption.REPLACE_EXISTING);

StandardCopyOption可以替换。

5 文件移动

        Path source1 = Paths.get("D:/channel/a.txt");
        Path source2 = Paths.get("D:/channel/b.txt");
        Files.move(source1,source2);
        //保证文件移动原子性
        Files.move(source1,source2, StandardCopyOption.ATOMIC_MOVE);
       

6 文件删除

        Path source1 = Paths.get("D:/channel/a.txt");
        Files.delete(source1);

如果文件不存在,有如下异常:

Exception in thread "main" java.nio.file.NoSuchFileException:

7 文件遍历

    public static void main(String[] args) throws IOException {
        AtomicInteger a1=new AtomicInteger();
        AtomicInteger a2=new AtomicInteger();
        Files.walkFileTree(Paths.get("E:\\Go"),new SimpleFileVisitor<>(){
            @Override
            public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs)
                    throws IOException {
                System.out.println("====="+dir);
                a1.getAndIncrement();
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
                    throws IOException {
                System.out.println("====="+file);
                a2.getAndIncrement();
                return super.visitFile(file, attrs);
            }
        });
        System.out.println("文件夹数量=="+a1);
        System.out.println("文件数量=="+a2);
    }

8删除多级目录

  public static void main(String[] args) throws IOException {
       Files.delete(Paths.get("D:\\channel"));
    }

直接删除多级目录,会有异常:

Exception in thread "main" java.nio.file.DirectoryNotEmptyException:
    public static void main(String[] args) throws IOException {
       Files.walkFileTree(Paths.get("D:\\channel"),new SimpleFileVisitor<>(){
           @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
                   throws IOException {
               //先删除文件
               Files.delete(file);
               return super.visitFile(file, attrs);
           }

           @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc)
                   throws IOException {
               //后删除文件夹
               Files.delete(dir);
               return super.postVisitDirectory(dir, exc);
           }
       });
    }

9 多级目录拷贝

    public static void main(String[] args) throws IOException {
       Files.walk(Paths.get("D:\\channel")).forEach(path->{
           String target = path.toString().replace("D:\\channel", "D:\\channel2");
           try {
               if(Files.isDirectory(path)){
                    Files.createDirectory(Paths.get(target));
               }else if(Files.isRegularFile(path)){//普通文件
                    Files.copy(path,Paths.get(target));
               }
           }catch (Exception e){
           }
       });
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值