问题
I cant able to rename the folder which contains a files or sub folders in it.
My Folder structure is
D:
root
popcorn-folder1
popcorn-subfolder1
popcorn-subfile1
popcorn-file1
popcorn-folder2
popcorn-subfolder2
popcorn-file2
My resulting Directory should be
D:
root
folder1
subfolder1
subfile1
file1
folder2
subfolder2
file2
My tried code is
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)
the implementation is based on this article Java NIO Files
This is sequel of Renaming a folder name which has sub directories is not working using java File.rename.to()
EDIT: I have enabled the write permission for all the folders and files.
But there is no answer to it.
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)
回答1:
As mentioned in the java docs of Java nio library -
java.nio.file.AccessDeniedException is a Checked exception thrown when a file system operation is denied, typically due to a file permission or other access check.
Your first step to solve this problem is to check if you have write permissions to the whole directory you are trying to change his name.
回答2:
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").
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
}
}
}
}
¹: FileAlreadyExistsException
would be thrown when you use Files.move(sourcePath, destinationPath)
and the destination already exists.
²: 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.
来源:https://stackoverflow.com/questions/48320280/how-to-rename-the-folders-and-subfolders-including-the-files-present-in-it-recur