Skip to content

Instantly share code, notes, and snippets.

@mkeskells
Created February 6, 2018 23:14
Show Gist options
  • Save mkeskells/9cca911f083a906eef72833496daa3f0 to your computer and use it in GitHub Desktop.
Save mkeskells/9cca911f083a906eef72833496daa3f0 to your computer and use it in GitHub Desktop.
sbt delete
import java.io.{File, IOException}
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file._
object test extends App {
def copyFiles = {
target.mkdirs()
val process = new ProcessBuilder().command("xcopy","s:\\source","S:\\target","/s/h/e/k/f/c/i/q").inheritIO().start()
process.waitFor()
//wait for the SSD to flush - makes the timing stable
Thread.sleep(1000)
}
val target = new File("S:/target")
//warmup
copyFiles
IO.delete(target)
copyFiles
IO.newDelete(target)
for (i <- 1 to 5) {
copyFiles
time(s"old delete $i", IO.delete(target))
copyFiles
time(s"new delete $i", IO.newDelete(target))
}
def time (msg:String, fn: => Unit): Unit = {
val start = System.nanoTime()
fn
val end = System.nanoTime()
println(s"$msg took ${(end-start)/1000/1000.0} ms")
}
}
object IO {
import ErrorHandling._
/** Returns the children of directory `dir` in a non-null array. */
def listFiles(dir: File): Array[File] = wrapNull(dir.listFiles())
private def wrapNull(a: Array[File]) = if (a == null) new Array[File](0) else a
/** Deletes each file or directory (recursively) in `files`. */
def delete(files: Iterable[File]): Unit = files.foreach(delete)
///OLD code
/** Deletes `file`, recursively if it is a directory. */
def delete(file: File): Unit = {
translate("Error deleting file " + file + ": ") {
val deleted = file.delete()
if (!deleted && file.isDirectory) {
delete(listFiles(file))
file.delete
()
}
}
}
def newDelete(file: File): Unit = {
object deleter extends SimpleFileVisitor[Path] {
override def visitFile(path: Path, attr: BasicFileAttributes): FileVisitResult = {
Files.delete(path)
FileVisitResult.CONTINUE
}
override def postVisitDirectory(dir: Path, e: IOException): FileVisitResult = {
if (e eq null) {
Files.delete(dir)
FileVisitResult.CONTINUE
} else throw e // directory iteration failed
}
}
Files.walkFileTree(file.toPath, deleter)
}
}
object ErrorHandling {
def translate[T](msg: => String)(f: => T) =
try {
f
} catch {
case e: IOException => throw new TranslatedIOException(msg + e.toString, e)
case e: Exception => throw new TranslatedException(msg + e.toString, e)
}
def wideConvert[T](f: => T): Either[Throwable, T] =
try {
Right(f)
} catch {
case ex@(_: Exception | _: StackOverflowError) => Left(ex)
case err@(_: ThreadDeath | _: VirtualMachineError) => throw err
case x: Throwable => Left(x)
}
def convert[T](f: => T): Either[Exception, T] =
try {
Right(f)
} catch {
case e: Exception => Left(e)
}
def reducedToString(e: Throwable): String =
if (e.getClass == classOf[RuntimeException]) {
val msg = e.getMessage
if (msg == null || msg.isEmpty) e.toString else msg
} else
e.toString
}
sealed class TranslatedException (msg: String, cause: Throwable)
extends RuntimeException(msg, cause) {
override def toString = msg
}
final class TranslatedIOException (msg: String, cause: IOException)
extends TranslatedException(msg, cause)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment