如何使用Java NIO文件递归重命名文件夹和子文件夹(包括其中包含的文件)? [英] How to rename the folders and subfolders including the files present in it recursively using Java NIO Files?

查看:129
本文介绍了如何使用Java NIO文件递归重命名文件夹和子文件夹(包括其中包含的文件)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法重命名其中包含文件或子文件夹的文件夹.

I cant able to rename the folder which contains a files or sub folders in it.

我的文件夹结构是

D:
  root
      popcorn-folder1     
           popcorn-subfolder1   
               popcorn-subfile1
           popcorn-file1         
      popcorn-folder2 
           popcorn-subfolder2  
           popcorn-file2 

我生成的目录应该是

D:
  root
      folder1     
           subfolder1   
               subfile1
           file1         
      folder2 
           subfolder2  
           file2  

我尝试过的代码是

package com.din.pach;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

public class FileNio {

public static void main(String[] args) throws IOException {

    Path sourcePath      = Paths.get("D:\\root\\");

    Files.walkFileTree(sourcePath, new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            // System.out.println("pre visit dir:" + dir);
            //rename(dir);
            //renameFile(dir);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            //System.out.println("visit file: " + file);
            renameFile(file);
            System.out.println("====================================================================");
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            //   System.out.println("visit file failed: " + file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            //  System.out.println("post visit directory: " + dir);
            renameDirectory(dir);
            return FileVisitResult.CONTINUE;
        }



    });



}

public static void renameFile(Path file) throws IOException {


    boolean isDirectory = Files.isDirectory(file);
    boolean isWritable = Files.isWritable(file);
    System.out.println("isDirectory-> "+isDirectory);
    System.out.println("isWritable-> "+isWritable);

    Path sourcePath      = Paths.get(file.toString());
    String origName = file.getFileName().toString();
    String newName = origName.replaceAll("POPCORN-", "");
    if (isWritable&&!isDirectory) {




        System.out.println("fname-> "+origName);
        /*get the path of the directory*/
        String baseLoc = file.getParent().toString();
        System.out.println("baseLoc-> "+baseLoc);
        if (origName.contains("POPCORN-")  /*|| origName.contains("#") || origName.contains("@")*/){

            System.out.println("Orig name-> "+origName);
            /*origName = origName.replaceAll("&", "_and_");
        origName = origName.replaceAll("@", "_at_");*/


            System.out.println("New Name-> "+newName);
            String newLoc = baseLoc+File.separator+newName;//having "/" hardcoded is not cross-platform.
            System.out.println("newLoc-> "+newLoc);
            //File newFile = new File(newLoc);


            Path destinationPath = Paths.get(newLoc);

            Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);

        } else {
            System.out.println("No write permission");
        }
    }else{

        /*if(origName.contains("POPCORN-")  || origName.contains("#") || origName.contains("@")){
            Files.copy(sourcePath, sourcePath.resolveSibling(newName),StandardCopyOption.REPLACE_EXISTING);
        }*/
    }
}



public static void renameDirectory(Path file) throws IOException {


    boolean isDirectory = Files.isDirectory(file);
    boolean isWritable = Files.isWritable(file);
    System.out.println("isDirectory-> "+isDirectory);
    System.out.println("isWritable-> "+isWritable);

    Path sourcePath      = Paths.get(file.toString());
    String origName = file.getFileName().toString();
    String newName = origName.replaceAll("POPCORN-", "");
    if (isWritable&&isDirectory) {

            if(origName.contains("POPCORN-")  /*|| origName.contains("#") || origName.contains("@")*/){
                Files.move(sourcePath, sourcePath.resolveSibling(newName),StandardCopyOption.ATOMIC_MOVE);
            }

        } else {
            System.out.println("No write permission");
        }
    }
}

在上面的代码中,我可以成功重命名文件.但是下面抛出异常

In above code, I can rename the files successfully. But below exception is thrown

Exception in thread "main" java.nio.file.AccessDeniedException: D:\root\POPCORN-folder1 -> D:\root\folder1
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileCopy.move(Unknown Source)
at sun.nio.fs.WindowsFileSystemProvider.move(Unknown Source)
at java.nio.file.Files.move(Unknown Source)
at com.din.pach.FileNio.renameDirectory(FileNio.java:121)
at com.din.pach.FileNio$1.postVisitDirectory(FileNio.java:45)
at com.din.pach.FileNio$1.postVisitDirectory(FileNio.java:1)
at java.nio.file.Files.walkFileTree(Unknown Source)
at java.nio.file.Files.walkFileTree(Unknown Source)
at com.din.pach.FileNio.main(FileNio.java:19)

该实现基于本文 Java NIO文件

这是使用Java File.rename.to()重命名具有子目录的文件夹名称后的结果

我已经为所有文件夹和文件启用了写权限.

I have enabled the write permission for all the folders and files.

但是没有答案.

更新:更新了完整控制台输出

UPDATE: updated the Full console output

   isDirectory-> false
   isWritable-> true
   fname-> popcorn-file1.txt
   baseLoc-> D:\root\popcorn-folder1
   Orig name-> popcorn-file1.txt
   New Name-> file1.txt
   newLoc-> D:\root\popcorn-folder1\file1.txt
   ====================================================================
   isDirectory-> false
   isWritable-> true
   fname-> popcorn-subfile1.txt
   baseLoc-> D:\root\popcorn-folder1\popcorn-subfolder1
   Orig name-> popcorn-subfile1.txt
   New Name-> subfile1.txt
   newLoc-> D:\root\popcorn-folder1\popcorn-subfolder1\subfile1.txt
   ====================================================================
   isDirectory-> true
   isWritable-> true
   isDirectory-> true
   isWritable-> true
   Exception in thread "main" java.nio.file.AccessDeniedException: D:\root\popcorn-folder1 -> D:\root\folder1
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileCopy.move(Unknown Source)
at sun.nio.fs.WindowsFileSystemProvider.move(Unknown Source)
at java.nio.file.Files.move(Unknown Source)
at com.din.pach.FileNio.renameDirectory(FileNio.java:121)
at com.din.pach.FileNio$1.postVisitDirectory(FileNio.java:45)
at com.din.pach.FileNio$1.postVisitDirectory(FileNio.java:1)
at java.nio.file.Files.walkFileTree(Unknown Source)
at java.nio.file.Files.walkFileTree(Unknown Source)
at com.din.pach.FileNio.main(FileNio.java:19)

推荐答案

不幸的是,由于您的问题仅包含大量经过修改和整理的样本数据,因此很难发现此问题的真正来源.
实际上,您试图为两个或多个文件夹分配相同的名称. (例如,"folder1"和"folder2"都应重命名为"directory").

Unfortunately the real source of this problem is hard to detect, since your question only contains heavy modified and trimmed sample data.
Actually you tried to assign the same name too two or more folders. (e.g. "folder1" and "folder2" both should be renamed to "directory").

由于设置了CopyOption StandardCopyOption.ATOMIC_MOVE,您只会得到具有误导性的java.nio.file.AccessDeniedException而不是FileAlreadyExistsException¹或DirectoryNotEmptyException².

Since the CopyOption StandardCopyOption.ATOMIC_MOVE is set you only get the misleading java.nio.file.AccessDeniedException instead of FileAlreadyExistsException¹ or DirectoryNotEmptyException².

现在要避免这种情况,您需要检查该文件夹是否已经存在:

Now to avoid this you need to check if the folder already exists:

public static void renameDirectory(Path file) throws IOException {
    boolean isDirectory = Files.isDirectory(file);
    if(isDirectory) {
        Path sourcePath = Paths.get(file.toString());
        String origName = file.getFileName().toString();

        if(origName.contains("POPCORN-")) {
            String newName = origName.replaceAll("POPCORN-", "");
            Path destinationPath = sourcePath.resolveSibling(newName);

            // Check if the folder doesn't exists
            if(!Files.exists()) {
                // You can rename the folder without any difficulty
                Files.move(sourcePath, destinationPath, StandardCopyOption.ATOMIC_MOVE);
            } else {
                // Print warning
                System.err.println("Directory already exists! Try to rename \""+sourcePath+"\" to \""+destinationPath+"\"");
                // Here you could add some code to propably handel this case. e.g. merge the folders or create another name
            }
        }
    }
}


¹:当您使用Files.move(sourcePath, destinationPath)并且目标已经存在时,将抛出FileAlreadyExistsException.


¹: FileAlreadyExistsException would be thrown when you use Files.move(sourcePath, destinationPath) and the destination already exists.

²:当您使用Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING)时,将抛出DirectoryNotEmptyException并且目标位置的文件夹包含文件或文件夹.

²: DirectoryNotEmptyException would be thrown when you use Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING) and the folder at the destination contains a file or folder.

这篇关于如何使用Java NIO文件递归重命名文件夹和子文件夹(包括其中包含的文件)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆