Netty基础02-NIO-文件编程

3、文件编程

FileChannel

获取

  • FileChannle只能在阻塞模式下使用

  • 不能直接打开FileChannel,必须通过FileInputStream、FileOutputStream或者RandomAccessFile来获取FileChannel,它们都有getChannel方法

  • 通过FileInputStream获取的channel只能读

  • 通过FileOutputStream获取的channel只能写

  • 通过RandomAccessFile是否能读写根据构造的RandomAccessFile时的读写模式决定

读取

  • 会从channel读取数据跳虫ByteBuffer,返回值表示读到了多少个字节,-1表示到达了文件的末尾

  • int readBytes = channel.read(buffer);
    

写入

  • 写入的正确姿势如下

  • ByteBuffer buffer = ...;
    buffer.put(...); // 存入数据
    buffer,flip(); // 切换读模式
    while(buffer.hasRemaining()) {
        channel.write(buffer);
    }
    

    在while中调用channel.write方法并不一定保证一次将buffer中的全部内容写入channel

关闭

  • channel必须关闭,不过调用了FileInoutStream、FileOutputStream或者RandomAccessFile的close方法会间接调用channel的close方法

位置

  • 获取当前位置

    long pos = channel.position();
    
  • 设置当前位置

    long newPos = ....;
    channel.position(newPos);
    
  • 设置当前位置时,如果设置为未见末尾

    这时读取会返回-1

    这时写入,会追加内容,但要注意如果position超过了文件末尾,再写入新内容和原来末尾之间会有空洞(00)

大小

  • 使用size方法获取文件大小

强制写入

  • 操作系统处于性能的考虑,会将数据缓存,不是立刻写入磁盘,可以调用force(true)方法将文件内容和元数据(文件的权限等信息立刻写入磁盘)

两个channel传输数据

    public static void main(String[] args) {
        String source = "word1.txt";
        String target = "word3.txt";
        try (
                FileChannel from = new FileInputStream(source).getChannel();
                FileChannel to = new FileOutputStream(target).getChannel();
        ) {
            // 代码简洁,效率高,底层一版会调用操作系统的零拷贝优化shangxin
            // 传输数据有上限,最多2G
            from.transferTo(0, from.size(), to);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

优化(可传输大于2G的文件):

    public static void main(String[] args) {
        String source = "word1.txt";
        String target = "word4.txt";
        try (
                FileChannel from = new FileInputStream(source).getChannel();
                FileChannel to = new FileOutputStream(target).getChannel();
        ) {

            long size = from.size();
            // left  表示还有多少字节
            for (long left = size; left > 0; ) {
                System.out.println("position:"+(size-left)+",left:"+left);
                left -= from.transferTo((size - left), left, to);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

Path

  • JDK 引入Path和Paths类

  • Path用来表示文件路径

  • Paths时工具类,用来获取Path

    // 相对路径 使用usr.dir 环境变量来定位 word1.txt
    Path path = Paths.get("word1.txt");
    // 绝对路径
    Path path2 = Paths.get("E:\\210107TEST\\AkeyStart\\AkeyStart.bat");
    // 绝对路径
    Path path1 = Paths.get("E:/210107TEST/AkeyStart/AkeyStart.bat");
    // 代表 E:/210107TEST/AkeyStart/AkeyStart.bat
    Path path3 = Paths.get("E:/210107TEST/AkeyStart", "AkeyStart.bat");
    
    • **. **代表当前路径

    • ..代表了上一级路径

```java
  Path path4 = Paths.get("E:\\210107TEST\\AkeyStart\\AkeyStart.bat\\..\\AkeyStart - 副本.bat");
  System.out.println(path4);
  System.out.println(path4.normalize());

  E:\210107TEST\AkeyStart\AkeyStart.bat\..\AkeyStart - 副本.bat
  E:\210107TEST\AkeyStart\AkeyStart - 副本.bat
```

File

  • 检查文件是否存在

    Path path = Paths.get("word10.txt");
    System.out.println(Files.exists(path)); // true false
    
    
  • 创建一级目录

      Path path1 = Paths.get("E:\\kms\\dgj");
      Files.createDirectory(path1);
    
  • 创建多级目录

     Path path1 = Paths.get("E:\\kms\\test\\dgj");
     Files.createDirectories(path1);
    
  • 拷贝文件

    // word10.txt没有
    Path path1 = Paths.get("word1.txt");
     Path path2 = Paths.get("word10.txt");
     Files.copy(path1,path2);
    
    // word2.txt有,覆盖
     Path path1 = Paths.get("word1.txt");
     Path path2 = Paths.get("word2.txt");
    Files.copy(path1,path2, StandardCopyOption.REPLACE_EXISTING);
    

    ​ 如果文件存在,抛 java.nio.file.FileAlreadyExistsException

  • 移动文件

      Path path1 = Paths.get("word1.txt");
      Path path2 = Paths.get("word2.txt");
      // StandardCopyOption.ATOMIC_MOVE 保证文件移动的原子性
      Files.move(path1,path2,StandardCopyOption.ATOMIC_MOVE);
    
  • 删除文件

    Path path1 = Paths.get("word2.txt");
    Files.delete(path1);
    

    ​ 文件不存在:java.nio.file.NoSuchFileException: word21.txt

  • 删除目录

    Path path1 = Paths.get("E:\\kms\\dgj");
    Files.delete(path1);
    
  • 遍历文件夹(访问者模式)

        public static void dirAndFile() {
            try {
                // 文件夹数
                AtomicInteger dircount = new AtomicInteger();
                // 文件数
                AtomicInteger filecount = new AtomicInteger();
                Files.walkFileTree(Paths.get("D:\\mavenjar"), new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)  throws IOException {
                        dircount.incrementAndGet();
                        System.out.println("dir--->:"+dir);
                        return FileVisitResult.CONTINUE;
                    }
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                            throws IOException
                    {
                        filecount.incrementAndGet();
                        System.out.println("file--->:"+file);
                        return FileVisitResult.CONTINUE;
                    }
                });
                System.out.println("dircount:"+dircount+"个文件");
                System.out.println("dircount:"+filecount+"个文件夹");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    遍历文件夹中有多少个jar

        public static void selectJar() {
            try {
                AtomicInteger atomicInteger = new AtomicInteger();
                Files.walkFileTree(Paths.get("D:\\mavenjar"), new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                            throws IOException {
                    if(file.toString().endsWith(".jar")){
                        atomicInteger.incrementAndGet();
                        System.out.println(file);
                    }
                        return super.visitFile(file,attrs);
                    }
                });
                System.out.println(atomicInteger);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
  • 删除多级目录

    Files.delete(Paths.get("D:\\ruoyi")); //java.nio.file.DirectoryNotEmptyException: D:\ruoyi 有文件 删除失败	
    
        public static void deleteDir() {
            // 删除多级目录
            try {
                Files.walkFileTree(Paths.get("D:\\ruoyi"), new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                            throws IOException {
                        Files.delete(file);
                        return super.visitFile(file, attrs);
                    }
    
                    @Override
                    public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                            throws IOException {
                        Files.delete(dir);
                        return FileVisitResult.CONTINUE;
                    }
    
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    • 文件夹拷贝

          public static void backups() throws IOException {
              String source = "D:\\代码备份";
              String target = "D:\\代码备份testnio";
      
              Files.walk(Paths.get(source)).forEach(path -> {
      
                  // 是否是目录
                  try {
                      String replace = path.toString().replace(source, target);
                      if (Files.isDirectory(path)) {
                          Files.createDirectory(Paths.get(replace));
                      }
                      // 是否是文件
                      else if (Files.isRegularFile(path)) {
                          Files.copy(path, Paths.get(replace));
                      }
                  } catch (IOException E) {
      
                  }
              });
              System.out.println("copy complete");
          }
      
posted @ 2021-04-19 22:32  一个努力的人QAQ  阅读(81)  评论(0编辑  收藏  举报