为什么此代码无法删除文件?

时间:2016-01-20 15:27:39

标签: scala

“学习Scala中的并发编程”中的一个例子:

package org.learningconcurrency

import java.io.File
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.{ConcurrentHashMap, ForkJoinPool, LinkedBlockingQueue}

import org.apache.commons.io.FileUtils

import scala.annotation.tailrec

/**
  * Created by kaiyin on 1/19/16.
  */
import org.learningconcurrency.ch3.Ch3.execute
import scala.collection.convert.decorateAsScala._

object Issue {

  sealed trait State

  class Idle extends State

  class Creating extends State

  class Copying(val n: Int) extends State

  class Deleting extends State

  class Entry(val isDir: Boolean) {
    val state = new AtomicReference[State](new Idle)

  }

  class FileSystem(val root: String) {
    val rootDir = new File(root)
    val files: collection.concurrent.Map[String, Entry] = new ConcurrentHashMap[String, Entry]().asScala
    for (f <- FileUtils.iterateFiles(rootDir, null, false).asScala)
      files.put(f.getName, new Entry(false))

    def deleteFile(filename: String): Unit = {
      files.get(filename) match {
        case None =>
          log(s"Path '$filename' does not exist!")
        case Some(entry) if entry.isDir =>
          log(s"Path '$filename' is a directory!")
        case Some(entry) => execute {
          if (prepareForDelete(entry))
            if (FileUtils.deleteQuietly(new File(filename)))
              files.remove(filename)
        }
      }
    }
  }

  @tailrec private def prepareForDelete(entry: Entry): Boolean = {
    val s0 = entry.state.get
    s0 match {
      case i: Idle =>
        if (entry.state.compareAndSet(s0, new Deleting)) true
        else prepareForDelete(entry)
      case c: Creating =>
        log("File is being created, cannot delete")
        false
      case c: Copying =>
        log("File is being created, cannot delete")
        false
      case d: Deleting =>
        false
    }
  }
  def main(args: Array[String]) {
    val fs = new FileSystem("/tmp")
    fs.files.foreach(println _)
    // Thread.sleep(500)
    fs.deleteFile("test")
  }
}

它只是检查一个文件的状态然后删除它,代码看起来应该可以工作,但是在运行之后,我touch /tmp/test创建的文件仍然存在。

1 个答案:

答案 0 :(得分:0)

问题与FileUtils.deleteQuietly(new File(filename))行有关。根据{{​​3}},deleteQuietly与File.delete()相同,但不是引发异常,而是在文件被删除时返回true,如果不是,则返回false

添加调试日志会显示deleteQuietly无效:

if (FileUtils.deleteQuietly(new File(filename))) {
  println("File was deleted!")
  files.remove(filename)      
} else {
  println("File was NOT deleted!")
}

应打印File was NOT deleted

那有什么不对?让我们检查您传递给deleteQuietly的参数:

println((new File(filename)).exists()) // returns false

似乎File找不到您的文件。缺少什么?

由于您只提供相对路径test,因此您还需要提供父目录:

    case Some(entry) => execute {
      if (prepareForDelete(entry))
        if (FileUtils.deleteQuietly(new File(rootDir, filename))) 
          files.remove(filename)
    }