我无法重命名包含文件或子文件夹的文件夹。
我的文件夹结构是
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");
}
}
}
在上面的代码中,我可以成功重命名文件。但是抛出以下异常
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 Files
这是Renaming a folder name which has sub directories is not working using java File.rename.to()
的续集编辑:我已为所有文件夹和文件启用了写入权限。
但是没有答案。
更新:更新了完整控制台输出
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)
答案 0 :(得分:0)
如Java nio库的java文档中所述 -
java.nio.file.AccessDeniedException是文件系统操作被拒绝时抛出的Checked异常,通常是由于文件权限或其他访问检查。
解决此问题的第一步是检查您是否对要更改其名称的整个目录具有写入权限。
答案 1 :(得分:0)
不幸的是,这个问题的真正根源很难被发现,因为您的问题只包含大量修改和修整的样本数据 实际上你试图为两个或更多文件夹分配相同的名称。 (例如“folder1”和“folder2”都应该重命名为“directory”)。
自设置CopyOption StandardCopyOption.ATOMIC_MOVE
后,您只会误导java.nio.file.AccessDeniedException
而不是FileAlreadyExistsException
¹或DirectoryNotEmptyException
²。
现在要避免这种情况,您需要检查文件夹是否已存在:
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
并且目的地已经存在时,¹:Files.move(sourcePath, destinationPath)
会被抛出。
²:当您使用DirectoryNotEmptyException
并且目标中的文件夹包含文件或文件夹时,将抛出Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING)
。