src/Pure/General/file.scala
author wenzelm
Fri, 20 Jul 2012 23:16:54 +0200
changeset 49426 5b3440850d36
child 49433 1a634f9614fb
permissions -rw-r--r--
more abstract file system operations in Scala, corresponding to ML version;
wenzelm@49426
     1
/*  Title:      Pure/General/file.scala
wenzelm@49426
     2
    Author:     Makarius
wenzelm@49426
     3
wenzelm@49426
     4
File system operations.
wenzelm@49426
     5
*/
wenzelm@49426
     6
wenzelm@49426
     7
package isabelle
wenzelm@49426
     8
wenzelm@49426
     9
wenzelm@49426
    10
import java.io.{BufferedWriter, OutputStreamWriter, FileOutputStream, BufferedOutputStream,
wenzelm@49426
    11
  InputStream, FileInputStream, BufferedReader, InputStreamReader, File => JFile, FileFilter}
wenzelm@49426
    12
import java.util.zip.GZIPOutputStream
wenzelm@49426
    13
wenzelm@49426
    14
import scala.collection.mutable
wenzelm@49426
    15
wenzelm@49426
    16
wenzelm@49426
    17
object File
wenzelm@49426
    18
{
wenzelm@49426
    19
  /* read */
wenzelm@49426
    20
wenzelm@49426
    21
  def read(reader: BufferedReader): String =
wenzelm@49426
    22
  {
wenzelm@49426
    23
    val output = new StringBuilder(100)
wenzelm@49426
    24
    var c = -1
wenzelm@49426
    25
    while ({ c = reader.read; c != -1 }) output += c.toChar
wenzelm@49426
    26
    reader.close
wenzelm@49426
    27
    output.toString
wenzelm@49426
    28
  }
wenzelm@49426
    29
wenzelm@49426
    30
  def read(stream: InputStream): String =
wenzelm@49426
    31
    read(new BufferedReader(new InputStreamReader(stream, Standard_System.charset)))
wenzelm@49426
    32
wenzelm@49426
    33
  def read(file: JFile): String = read(new FileInputStream(file))
wenzelm@49426
    34
wenzelm@49426
    35
  def read(path: Path): String = read(path.file)
wenzelm@49426
    36
wenzelm@49426
    37
wenzelm@49426
    38
  /* write */
wenzelm@49426
    39
wenzelm@49426
    40
  private def write_file(file: JFile, text: CharSequence, zip: Boolean)
wenzelm@49426
    41
  {
wenzelm@49426
    42
    val stream1 = new FileOutputStream(file)
wenzelm@49426
    43
    val stream2 = if (zip) new GZIPOutputStream(new BufferedOutputStream(stream1)) else stream1
wenzelm@49426
    44
    val writer = new BufferedWriter(new OutputStreamWriter(stream2, Standard_System.charset))
wenzelm@49426
    45
    try { writer.append(text) }
wenzelm@49426
    46
    finally { writer.close }
wenzelm@49426
    47
  }
wenzelm@49426
    48
wenzelm@49426
    49
  def write(file: JFile, text: CharSequence): Unit = write_file(file, text, false)
wenzelm@49426
    50
  def write(path: Path, text: CharSequence): Unit = write(path.file, text)
wenzelm@49426
    51
wenzelm@49426
    52
  def write_zip(file: JFile, text: CharSequence): Unit = write_file(file, text, true)
wenzelm@49426
    53
  def write_zip(path: Path, text: CharSequence): Unit = write_zip(path.file, text)
wenzelm@49426
    54
wenzelm@49426
    55
wenzelm@49426
    56
  /* copy */
wenzelm@49426
    57
wenzelm@49426
    58
  def eq(file1: JFile, file2: JFile): Boolean =
wenzelm@49426
    59
    file1.getCanonicalPath == file2.getCanonicalPath  // FIXME prefer java.nio.file.Files.isSameFile of Java 1.7
wenzelm@49426
    60
wenzelm@49426
    61
  def copy(src: JFile, dst: JFile)
wenzelm@49426
    62
  {
wenzelm@49426
    63
    if (!eq(src, dst)) {
wenzelm@49426
    64
      val in = new FileInputStream(src)
wenzelm@49426
    65
      try {
wenzelm@49426
    66
        val out = new FileOutputStream(dst)
wenzelm@49426
    67
        try {
wenzelm@49426
    68
          val buf = new Array[Byte](65536)
wenzelm@49426
    69
          var m = 0
wenzelm@49426
    70
          do {
wenzelm@49426
    71
            m = in.read(buf, 0, buf.length)
wenzelm@49426
    72
            if (m != -1) out.write(buf, 0, m)
wenzelm@49426
    73
          } while (m != -1)
wenzelm@49426
    74
        }
wenzelm@49426
    75
        finally { out.close }
wenzelm@49426
    76
      }
wenzelm@49426
    77
      finally { in.close }
wenzelm@49426
    78
    }
wenzelm@49426
    79
  }
wenzelm@49426
    80
wenzelm@49426
    81
  def copy(path1: Path, path2: Path): Unit = copy(path1.file, path2.file)
wenzelm@49426
    82
wenzelm@49426
    83
wenzelm@49426
    84
  /* misc */
wenzelm@49426
    85
wenzelm@49426
    86
  def with_tmp_file[A](prefix: String)(body: JFile => A): A =
wenzelm@49426
    87
  {
wenzelm@49426
    88
    val file = JFile.createTempFile(prefix, null)
wenzelm@49426
    89
    file.deleteOnExit
wenzelm@49426
    90
    try { body(file) } finally { file.delete }
wenzelm@49426
    91
  }
wenzelm@49426
    92
wenzelm@49426
    93
  // FIXME handle (potentially cyclic) directory graph
wenzelm@49426
    94
  def find_files(start: JFile, ok: JFile => Boolean): List[JFile] =
wenzelm@49426
    95
  {
wenzelm@49426
    96
    val files = new mutable.ListBuffer[JFile]
wenzelm@49426
    97
    val filter = new FileFilter { def accept(entry: JFile) = entry.isDirectory || ok(entry) }
wenzelm@49426
    98
    def find_entry(entry: JFile)
wenzelm@49426
    99
    {
wenzelm@49426
   100
      if (ok(entry)) files += entry
wenzelm@49426
   101
      if (entry.isDirectory) entry.listFiles(filter).foreach(find_entry)
wenzelm@49426
   102
    }
wenzelm@49426
   103
    find_entry(start)
wenzelm@49426
   104
    files.toList
wenzelm@49426
   105
  }
wenzelm@49426
   106
}
wenzelm@49426
   107