Java 在Scala中递归删除目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25999255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Delete directory recursively in Scala
提问by Michael
I am writing the following (with Scala 2.10 and Java 6):
我正在编写以下内容(使用 Scala 2.10 和 Java 6):
import java.io._
def delete(file: File) {
if (file.isDirectory)
Option(file.listFiles).map(_.toList).getOrElse(Nil).foreach(delete(_))
file.delete
}
How would you improve it ? The code seems working but it ignores the return value of java.io.File.delete
. Can it be done easier with scala.io
instead of java.io
?
你会如何改进它?该代码似乎有效,但它忽略了java.io.File.delete
. 可以用scala.io
而不是更容易java.io
吗?
回答by Gabriele Petronella
Using scala IO
使用Scala IO
import scalax.file.Path
val path = Path.fromString("/tmp/testfile")
try {
path.deleteRecursively(continueOnFailure = false)
} catch {
case e: IOException => // some file could not be deleted
}
or better, you could use a Try
或者更好,你可以使用 Try
val path: Path = Path ("/tmp/file")
Try(path.deleteRecursively(continueOnFailure = false))
which will either result in a Success[Int]
containing the number of files deleted, or a Failure[IOException]
.
这将导致Success[Int]
包含已删除文件数的 a 或Failure[IOException]
.
回答by roterl
Using java 6 without using dependencies this is pretty much the only way to do so.
The problem with your function is that it return Unit (which I btw would explicit note it using def delete(file: File): Unit = {
在不使用依赖项的情况下使用 java 6 这几乎是唯一的方法。
您的函数的问题在于它返回 Unit (顺便说一句,我会使用def delete(file: File): Unit = {
I took your code and modify it to return map from file name to the deleting status.
我接受了您的代码并对其进行了修改,以将映射从文件名返回到删除状态。
def delete(file: File): Array[(String, Boolean)] = {
Option(file.listFiles).map(_.flatMap(f => delete(f))).getOrElse(Array()) :+ (file.getPath -> file.delete)
}
回答by Garrett Hall
Try this code that throws an exception if it fails:
试试这个如果失败就会抛出异常的代码:
def deleteRecursively(file: File): Unit = {
if (file.isDirectory) {
file.listFiles.foreach(deleteRecursively)
}
if (file.exists && !file.delete) {
throw new Exception(s"Unable to delete ${file.getAbsolutePath}")
}
}
You could also fold or map over the delete if you want to return a value for all the deletes.
如果您想为所有删除返回一个值,您还可以折叠或映射删除。
回答by Dan Ciborowski - MSFT
From http://alvinalexander.com/blog/post/java/java-io-faq-how-delete-directory-tree
来自 http://alvinalexander.com/blog/post/java/java-io-faq-how-delete-directory-tree
Using Apache Common IO
使用 Apache 通用 IO
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
public void deleteDirectory(String directoryName)
throws IOException
{
try
{
FileUtils.deleteDirectory(new File(directoryName));
}
catch (IOException ioe)
{
// log the exception here
ioe.printStackTrace();
throw ioe;
}
}
The Scala one can just do this...
Scala 可以做到这一点......
import org.apache.commons.io.FileUtils
import org.apache.commons.io.filefilter.WildcardFileFilter
FileUtils.deleteDirectory(new File(outputFile))
回答by Pramit
This one uses java.io but one can delete directories matching it with wildcard string which may or may not contain any content within it.
这个使用 java.io 但可以删除与通配符字符串匹配的目录,其中可能包含也可能不包含任何内容。
for (file <- new File("<path as String>").listFiles;
if( file.getName() matches("[1-9]*"))) FileUtils.deleteDirectory(file)
Directory structure e.g. * A/1/, A/2/, A/300/ ... thats why the regex String: [1-9]*, couldn't find a File API in scala which supports regex(may be i missed something).
目录结构,例如 * A/1/, A/2/, A/300/ ... 这就是为什么 regex String: [1-9]*, 在 Scala 中找不到支持正则表达式的文件 API(可能是我错过了一些东西)。
回答by Julian Peeters
Getting little lengthy, but here's one that combines the recursivity of Garrette's solution with the npe-safety of the original question.
有点冗长,但这里有一个将 Garrette 解决方案的递归性与原始问题的 npe 安全性相结合的方法。
def deleteFile(path: String) = {
val penultimateFile = new File(path.split('/').take(2).mkString("/"))
def getFiles(f: File): Set[File] = {
Option(f.listFiles)
.map(a => a.toSet)
.getOrElse(Set.empty)
}
def getRecursively(f: File): Set[File] = {
val files = getFiles(f)
val subDirectories = files.filter(path => path.isDirectory)
subDirectories.flatMap(getRecursively) ++ files + penultimateFile
}
getRecursively(penultimateFile).foreach(file => {
if (getFiles(file).isEmpty && file.getAbsoluteFile().exists) file.delete
})
}
回答by Slavik Muz
This is recursive method that clean all in directory, and return count of deleted files
这是清除目录中所有内容的递归方法,并返回已删除文件的计数
def cleanDir(dir: File): Int = {
@tailrec
def loop(list: Array[File], deletedFiles: Int): Int = {
if (list.isEmpty) deletedFiles
else {
if (list.head.isDirectory && !list.head.listFiles().isEmpty) {
loop(list.head.listFiles() ++ list.tail ++ Array(list.head), deletedFiles)
} else {
val isDeleted = list.head.delete()
if (isDeleted) loop(list.tail, deletedFiles + 1)
else loop(list.tail, deletedFiles)
}
}
}
loop(dir.listFiles(), 0)
}
回答by Chris Martin
To add to Slavik Muz's answer:
添加到 Slavik Muz 的答案:
def deleteFile(file: File): Boolean = {
def childrenOf(file: File): List[File] = Option(file.listFiles()).getOrElse(Array.empty).toList
@annotation.tailrec
def loop(files: List[File]): Boolean = files match {
case Nil ? true
case child :: parents if child.isDirectory && child.listFiles().nonEmpty ?
loop((childrenOf(child) :+ child) ++ parents)
case fileOrEmptyDir :: rest ?
println(s"deleting $fileOrEmptyDir")
fileOrEmptyDir.delete()
loop(rest)
}
if (!file.exists()) false
else loop(childrenOf(file) :+ file)
}
回答by Vladimir Matveev
Using the Java NIO.2 API:
使用 Java NIO.2 API:
import java.nio.file.{Files, Paths, Path, SimpleFileVisitor, FileVisitResult}
import java.nio.file.attribute.BasicFileAttributes
def remove(root: Path): Unit = {
Files.walkFileTree(root, new SimpleFileVisitor[Path] {
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
Files.delete(file)
FileVisitResult.CONTINUE
}
override def postVisitDirectory(dir: Path, exc: IOException): FileVisitResult = {
Files.delete(dir)
FileVisitResult.CONTINUE
}
})
}
remove(Paths.get("/tmp/testdir"))
Really, it's a pity that the NIO.2 API is with us for so many years and yet few people are using it, even though it is really superior to the old File
API.
真的很遗憾,NIO.2 API 已经存在了这么多年,却很少有人使用它,尽管它确实优于旧的File
API。
回答by Mike Slinn
Expanding on Vladimir Matveev's NIO2 solution:
扩展 Vladimir Matveev 的 NIO2 解决方案:
object Util {
import java.io.IOException
import java.nio.file.{Files, Paths, Path, SimpleFileVisitor, FileVisitResult}
import java.nio.file.attribute.BasicFileAttributes
def remove(root: Path, deleteRoot: Boolean = true): Unit =
Files.walkFileTree(root, new SimpleFileVisitor[Path] {
override def visitFile(file: Path, attributes: BasicFileAttributes): FileVisitResult = {
Files.delete(file)
FileVisitResult.CONTINUE
}
override def postVisitDirectory(dir: Path, exception: IOException): FileVisitResult = {
if (deleteRoot) Files.delete(dir)
FileVisitResult.CONTINUE
}
})
def removeUnder(string: String): Unit = remove(Paths.get(string), deleteRoot=false)
def removeAll(string: String): Unit = remove(Paths.get(string))
def removeUnder(file: java.io.File): Unit = remove(file.toPath, deleteRoot=false)
def removeAll(file: java.io.File): Unit = remove(file.toPath)
}