问题描述
我无法重命名其中包含文件或子文件夹的文件夹.
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文件递归重命名文件夹和子文件夹(包括其中包含的文件)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!