Java “怎么做?”;“利用资源进行尝试”;在这个程序的上下文中实际工作,该程序删除给定目录节点下的所有文件和文件夹
此程序删除给定节点下的所有文件和文件夹 *编辑* 我在驱动器K上有以下“测试”目录结构:Java “怎么做?”;“利用资源进行尝试”;在这个程序的上下文中实际工作,该程序删除给定目录节点下的所有文件和文件夹,java,try-with-resources,directorystream,Java,Try With Resources,Directorystream,此程序删除给定节点下的所有文件和文件夹 *编辑* 我在驱动器K上有以下“测试”目录结构: Folder K:\garbage\ f_00000b (file) f_00000f ( " ) f_0000b3 ( " ) dir1 [FOLDER] Folder K:\garbage\dir1\ abc.pdf (file) b12.pdf (file) b36.pdf (file) dir2 [FOLDER] Folder K:\garbage\dir1\dir2\ A.pdf
Folder K:\garbage\
f_00000b (file)
f_00000f ( " )
f_0000b3 ( " )
dir1 [FOLDER]
Folder K:\garbage\dir1\
abc.pdf (file)
b12.pdf (file)
b36.pdf (file)
dir2 [FOLDER]
Folder K:\garbage\dir1\dir2\
A.pdf (file)
a1.pdf (file)
A2.pdf (file)
*结束编辑*
这个程序之所以有效,是因为我无意中发现了“尝试使用资源”,这条线被所有的资源所包围
import java.io.IOError;
导入java.io.IOException;
导入java.nio.file.DirectoryNotEmptyException;
导入java.nio.file.DirectoryStream;
导入java.nio.file.Files;
导入java.nio.file.NotDirectoryException;
导入java.nio.file.Path;
导入java.nio.file.path;
导入java.util.ArrayList;
导入javax.swing.JOptionPane;
公共类创建目录{
公共静态void main(字符串[]args){
删除该节点下的所有内容(path.get(“K:/garbage/dir1/dir2”);
}
静态void deleteAllFilesIn(字符串ps){
路径p=Path.get(ps);
试一试////////////////////////////////////////////////////////////////
(DirectoryStream路径=Files.newDirectoryStream(p))/////
{ //////////////////////////////////////////////////////////////////
for(路径q:路径)
删除(q);
}catch(notdirectorye异常){
System.out.println(“非目录:“+p.toString()+”--“+e”);
}捕获(DirectoryNotEmptyException e){
System.out.println(“非空:“+p.toString()+”--“+e”);
}
捕获(IOE异常){
System.out.println(“IO:+p.toString()+”--“+e”);
}
捕获(IOE错误){
System.out.println(“IO错误:+e”);
}
}
静态void删除此节点下的所有内容(路径p){
字符串sep=p.getFileSystem().getSeparator();
ArrayList pathPieces=新的ArrayList();
字符串[]路径=新字符串[p.getNameCount()];
对于(int i=0;i
我理解“尝试使用资源”是必要的:程序使用它,而不是没有它
但我不明白为什么,也不知道它是如何解决我现在描述的原始问题的
我最初将“资源”放置在try块上方,如下所示,这似乎是非常自然的:
DirectoryStream<Path> paths = Files.newDirectoryStream(p);
try {
for...
DirectoryStream path=Files.newDirectoryStream(p);
试一试{
对于
在程序结构完全相同的情况下,除了如上所示移动一行之外,所有文件和子文件夹都已成功从文件夹中删除,但引发了DirectoryNotEmptyException
。Windows资源管理器确认程序因异常终止后目录为空
为什么在空目录上引发异常
从“try with resources语句……声明……一个对象,该对象……在语句末尾关闭。”
关闭发生在语句的末尾,也发生在循环的末尾。即使使用try with resources,异常是如何不发生的
现在的情况是,在遍历整个节点之后,它下面的所有内容都被删除了
那么,try-with-resources实际上做了什么来删除一个空文件夹,如果不使用try-with-resources就无法删除它呢
这些问题看起来不像是愚蠢的问题,也不像是琐碎的情况
确实发生了
DirectoryNotEmptyException
异常,但尝试使用资源以某种方式处理它吗?我不敢相信我会问这个问题,因为这似乎是一个愚蠢的问题,但到底是什么让程序按预期运行的呢?在Windows上,您不能删除仍然打开的文件或目录。
(另一方面,在Unix上,这不是问题-删除文件时会将其从目录结构中删除,关闭文件时会将其从磁盘中删除。但在Unix上是这样的。)
因此,如果不使用try with resources语句关闭目录流,则在尝试删除父目录中的文件时,仍会打开子目录,并且尝试删除仍打开的子目录将失败。因为忽略异常(仅打印它们),随后删除父目录的尝试也将失败,并出现DirectoryNotEmptyException
,因为您没有删除所有子目录
您可以验证是否确实如此。如果不使用“尝试使用”资源,请确保在删除目录中的所有文件后明确关闭目录流(使用path.close();
)
这应该与try with resources块具有相同的效果(除非发生异常-为了保证与try with resources完全相同的行为,您需要将
path.close();
放在finally
块中).Erwin解释了您的问题,但在您的列表末尾,您还有一个相当严重的问题,在:
for(int k = p.getNameCount() - 1; k >= 0; k--)
deleteAllFilesIn(paths[k]);
创建路径零件列表,例如,其中的零件将:
- k:/garbage/dir1/dir2
- k:/garbage/dir1
- k:/垃圾
- k:/
删除此节点()下的所有内容。(我希望“回答我自己的问题”可以让线程的“底线”显示最终的工作结果。这样,查看线程的任何人都不必费劲寻找解决方案。)
不管怎样,这是我的建议
for(int k = p.getNameCount() - 1; k >= 0; k--)
deleteAllFilesIn(paths[k]);
static void deleteAllFilesBelowThisNode(String ps) throws IOException{
Path p = Paths.get(ps);
try
{
paths = Files.newDirectoryStream(p);
for(Path q: paths){
if(JOptionPane.showConfirmDialog(null,"Deleting " + q.toString(),"",
JOptionPane.OK_CANCEL_OPTION)
!= JOptionPane.OK_OPTION)
System.exit(9);
Files.delete(q);
System.out.println(q.toString() + " deleted");
}
}
finally{
JOptionPane.showMessageDialog(null,"AHA!");
paths.close();
}
}
Delete all entries beneath K:\garbage\dir1\dir2\
deleting K:\garbage\dir1\dir2\A.pdf ... deleted
deleting K:\garbage\dir1\dir2\a1 and 2 ver 2.pdf ... deleted
deleting K:\garbage\dir1\dir2\A1 and 2.pdf ... deleted
K:\garbage\dir1\dir2\ closed by finally. ----- THUS DELETEABLE
Delete all entries beneath K:\garbage\dir1\
deleting K:\garbage\dir1\abc.pdf ... deleted
deleting K:\garbage\dir1\b12.pdf ... deleted
deleting K:\garbage\dir1\b36.pdf ... deleted
deleting K:\garbage\dir1\dir2 ... ***DELETED***
K:\garbage\dir1\ closed by finally. ----- THUS DELETEABLE
Delete all entries beneath K:\garbage\
deleting K:\garbage\dir1 ... ***DELETED***
deleting K:\garbage\f_00000b ... deleted
deleting K:\garbage\f_00000f ... deleted
deleting K:\garbage\f_0000b3 ... deleted
K:\garbage\ closed by finally.
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class CreatingDirectories {
static void deleteAllFilesBelowThisNode(String ps) throws IOException{
DirectoryStream<Path> paths = null;
try
{
paths = Files.newDirectoryStream(Paths.get(ps));
for(Path q: paths){
System.out.print("deleting " + q.toString() + " ... ");
if(JOptionPane.showConfirmDialog(null,"Deleting " + q.toString(),"",
JOptionPane.OK_CANCEL_OPTION)
!= JOptionPane.OK_OPTION)
System.exit(9);
Files.delete(q);
System.out.println("deleted");
}
}
finally{
paths.close();
System.out.println("\n" + ps + " closed by finally.\n");
}
}
static void iterativelyDeleteFoldersFromHereUpToRoot(Path p) throws IOException{
String sep = p.getFileSystem().getSeparator();
ArrayList<String> pathPieces = new ArrayList<>() ;
String [] paths = new String[p.getNameCount()];
for(int i = 0 ; i < p.getNameCount() ; i++){
pathPieces.add(p.getName(i).toString());
paths[i] = p.getRoot().toString();
}
for(int i = 0; i < p.getNameCount() ; i++)
for(int k = 0; k <= i; k++)
paths[i] += pathPieces.get(k) + sep;
for(int k = p.getNameCount() - 1; k >= 0; k--){
System.out.println("\nDelete all entries beneath " + paths[k].toString());
deleteAllFilesBelowThisNode(paths[k]);
}
}
public static void main(String[] args) throws IOException {
iterativelyDeleteFoldersFromHereUpToRoot(Paths.get("K:/garbage/dir1/dir2"));
}
}