2014-09-23 4 views
12

에 나는이 (스칼라 2.10 및 Java 6) 다음 쓰고 있어요? 코드가 작동하는 것 같지만 java.io.File.delete의 반환 값을 무시합니다. java.io 대신 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 
} 

이상을 사용

+0

, 나는 함축이 훨씬 쉬워에 대한 읽기 느낌 :'에 대한 (목록 <- 옵션 (file.listFiles()); 아이 <- 목록) 삭제 (자식) ' –

+0

해당 옵션을 만들고이를 통해 매핑하는 것은 무엇입니까? 간단한 "file.listFiles.foreach (delete)"의 문제점은 무엇입니까? –

+1

@ViliusNormantas'listFiles'는'null'을 반환 할 수 있으므로'null'을 검사하거나'Option'으로 감싸 야합니다. 또한 당신은 아마도 두 가지 경우를 구분해야 할 것입니다 : (1)'listFiles'는 빈 배열을 반환하고 (2)'listFiles'는 null을 반환합니다 (I/O 오류 발생) – Michael

답변

14

, 당신도 삭제 된 파일의 번호 또는 Failure[IOException]을 포함하는 Success[Int] 발생하는 Try

val path: Path = Path ("/tmp/file") 
Try(path.deleteRecursively(continueOnFailure = false)) 

를 사용할 수 있습니다.

+1

감사합니다. 나는 외부 의존성을 사용하고 싶지 않다. – Michael

2

종속성을 사용하지 않고 java 6을 사용하면 이렇게 할 수있는 유일한 방법입니다.
함수의 문제는 단위 (반환한다는 것입니다 나는 BTW 명시 적 내가 코드를 가져다가 삭제 된 상태로 파일 이름에서 맵을 반환하도록 수정 def delete(file: File): Unit = {

사용하여주의 것이다.

def delete(file: File): Array[(String, Boolean)] = { 
    Option(file.listFiles).map(_.flatMap(f => delete(f))).getOrElse(Array()) :+ (file.getPath -> file.delete) 
} 
+0

하나 (okiittedly long;)) 라이너! – javadba

+0

symlink가있는 디렉토리에서는 작동하지 않습니다. – ine

14

실패하면 예외가 발생합니다이 코드를 시도해보십시오. 또한 배하거나 모든 삭제에 대한 값을 반환 할 경우 삭제를 통해 매핑 할 수 있습니다

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}") 
} 

아파치 공통 IO를 사용 http://alvinalexander.com/blog/post/java/java-io-faq-how-delete-directory-tree

에서

+0

재귀 구조가 좋습니다. – javadba

8

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; 
    } 
} 

만이 할 수있는 스칼라 하나 ...

import org.apache.commons.io.FileUtils 
import org.apache.commons.io.filefilter.WildcardFileFilter 
FileUtils.deleteDirectory(new File(outputFile)) 

Maven Repo Imports

1

이 하나가 java.io를 사용하지만 하나는 와일드 카드 문자열과 일치하는 디렉토리를 삭제할 수 있습니다. 그 안에 내용을 포함 할 수도 있고 포함하지 않을 수도 있습니다.

디렉토리 구조* A/1 /, A/300/... thats 왜 정규 표현식을 지원하는 스칼라에서 File API를 찾을 수없는 String : [1-9] * (내가 놓친 것일 수 있습니다.).

1

오래 걸리지 만, 원래 질문의 npe-safety와 Garrette 솔루션의 재귀를 결합한 것입니다.

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) 
} 
1

이것은 모든 디렉토리에 청소하고, 선택 Slavik MUZ의 대답에 추가하려면 삭제 된 파일

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) 
    } 
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")) 

NIO.2 API가 오랜 세월 동안 우리와 함께했지만 실제로는 이전의 File API보다 우수하지만 실제로 사용하는 사용자는 거의 없습니다. 블라디미르 Matveev의 NIO2 솔루션을 확장

2

자바 NIO.2 사용 :

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 
    }) 
} 
1

: 개인적으로

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) 
}