| author | wenzelm | 
| Tue, 18 Mar 2014 12:25:17 +0100 | |
| changeset 56202 | 0a11d17eeeff | 
| parent 54440 | 2c4940d2edf7 | 
| child 56428 | 1acf2d76ac23 | 
| permissions | -rw-r--r-- | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/General/file.scala | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 3 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 4 | File system operations. | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 6 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 8 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 9 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 10 | import java.io.{BufferedWriter, OutputStreamWriter, FileOutputStream, BufferedOutputStream,
 | 
| 51504 | 11 | OutputStream, InputStream, FileInputStream, BufferedInputStream, BufferedReader, | 
| 12 | InputStreamReader, File => JFile, IOException} | |
| 50684 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 13 | import java.util.zip.{GZIPInputStream, GZIPOutputStream}
 | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 14 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 15 | import scala.collection.mutable | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 16 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 17 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 18 | object File | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 19 | {
 | 
| 48613 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 20 | /* directory content */ | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 21 | |
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 22 | def read_dir(dir: Path): List[String] = | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 23 |   {
 | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 24 |     if (!dir.is_dir) error("Bad directory: " + dir.toString)
 | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 25 | val files = dir.file.listFiles | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 26 | if (files == null) Nil | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 27 | else files.toList.map(_.getName) | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 28 | } | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 29 | |
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 30 | def find_files(dir: Path): Stream[Path] = | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 31 |     read_dir(dir).toStream.map(name => {
 | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 32 | val path = dir + Path.basic(name) | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 33 | path #:: (if (path.is_dir) find_files(path) else Stream.empty) | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 34 | }).flatten | 
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 35 | |
| 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 36 | |
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 37 | /* read */ | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 38 | |
| 54440 | 39 | def read(file: JFile): String = Bytes.read(file).toString | 
| 48913 
f686cb016c0c
more direct File.read_bytes -- avoid cumulative copying of StringBuilder;
 wenzelm parents: 
48613diff
changeset | 40 | def read(path: Path): String = read(path.file) | 
| 
f686cb016c0c
more direct File.read_bytes -- avoid cumulative copying of StringBuilder;
 wenzelm parents: 
48613diff
changeset | 41 | |
| 50684 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 42 | |
| 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 43 | def read_stream(reader: BufferedReader): String = | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 44 |   {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 45 | val output = new StringBuilder(100) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 46 | var c = -1 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 47 |     while ({ c = reader.read; c != -1 }) output += c.toChar
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 48 | reader.close | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 49 | output.toString | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 50 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 51 | |
| 50684 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 52 | def read_stream(stream: InputStream): String = | 
| 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 53 | read_stream(new BufferedReader(new InputStreamReader(stream, UTF8.charset))) | 
| 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 54 | |
| 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 55 | def read_gzip(file: JFile): String = | 
| 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 56 | read_stream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file)))) | 
| 51504 | 57 | |
| 50684 
12b7e0b4a66e
support File.read_gzip as well, in accordance to File.write_gzip;
 wenzelm parents: 
50203diff
changeset | 58 | def read_gzip(path: Path): String = read_gzip(path.file) | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 59 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 60 | |
| 50845 | 61 | /* read lines */ | 
| 62 | ||
| 63 | def read_lines(reader: BufferedReader, progress: String => Unit): List[String] = | |
| 64 |   {
 | |
| 65 | val result = new mutable.ListBuffer[String] | |
| 66 | var line: String = null | |
| 51251 
d55cce4d72dd
more permissive File.read_lines, which is relevant for Managed_Process join/kill;
 wenzelm parents: 
50845diff
changeset | 67 |     while ({ line = try { reader.readLine} catch { case _: IOException => null }; line != null }) {
 | 
| 50845 | 68 | progress(line) | 
| 69 | result += line | |
| 70 | } | |
| 71 | reader.close | |
| 72 | result.toList | |
| 73 | } | |
| 74 | ||
| 75 | ||
| 48550 | 76 | /* try_read */ | 
| 77 | ||
| 78 | def try_read(paths: Seq[Path]): String = | |
| 79 |   {
 | |
| 80 | val buf = new StringBuilder | |
| 81 |     for (path <- paths if path.is_file) {
 | |
| 82 | buf.append(read(path)) | |
| 83 |       buf.append('\n')
 | |
| 84 | } | |
| 85 | buf.toString | |
| 86 | } | |
| 87 | ||
| 88 | ||
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 89 | /* write */ | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 90 | |
| 52671 
9a360530eac8
separate module XZ_File to avoid initial dependency on org.tukaani.xz;
 wenzelm parents: 
51982diff
changeset | 91 | def write_file(file: JFile, text: Iterable[CharSequence], | 
| 51982 | 92 | make_stream: OutputStream => OutputStream) | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 93 |   {
 | 
| 51504 | 94 | val stream = make_stream(new FileOutputStream(file)) | 
| 95 | val writer = new BufferedWriter(new OutputStreamWriter(stream, UTF8.charset)) | |
| 51982 | 96 |     try { text.iterator.foreach(writer.append(_)) }
 | 
| 97 |     finally { writer.close }
 | |
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 98 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 99 | |
| 51982 | 100 | def write(file: JFile, text: Iterable[CharSequence]): Unit = write_file(file, text, (s) => s) | 
| 101 | def write(file: JFile, text: CharSequence): Unit = write(file, List(text)) | |
| 102 | def write(path: Path, text: Iterable[CharSequence]): Unit = write(path.file, text) | |
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 103 | def write(path: Path, text: CharSequence): Unit = write(path.file, text) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 104 | |
| 51982 | 105 | def write_gzip(file: JFile, text: Iterable[CharSequence]): Unit = | 
| 51504 | 106 | write_file(file, text, (s: OutputStream) => new GZIPOutputStream(new BufferedOutputStream(s))) | 
| 51982 | 107 | def write_gzip(file: JFile, text: CharSequence): Unit = write_gzip(file, List(text)) | 
| 108 | def write_gzip(path: Path, text: Iterable[CharSequence]): Unit = write_gzip(path.file, text) | |
| 48494 | 109 | def write_gzip(path: Path, text: CharSequence): Unit = write_gzip(path.file, text) | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 110 | |
| 53336 | 111 | def write_backup(path: Path, text: CharSequence) | 
| 112 |   {
 | |
| 113 | path.file renameTo path.backup.file | |
| 114 | File.write(path, text) | |
| 115 | } | |
| 116 | ||
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 117 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 118 | /* copy */ | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 119 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 120 | def eq(file1: JFile, file2: JFile): Boolean = | 
| 49673 
2a088cff1e7b
more robust File.eq, and thus File.copy of "~~/lib/logo/isabelle.gif";
 wenzelm parents: 
49610diff
changeset | 121 |     try { java.nio.file.Files.isSameFile(file1.toPath, file2.toPath) }
 | 
| 
2a088cff1e7b
more robust File.eq, and thus File.copy of "~~/lib/logo/isabelle.gif";
 wenzelm parents: 
49610diff
changeset | 122 |     catch { case ERROR(_) => false }
 | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 123 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 124 | def copy(src: JFile, dst: JFile) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 125 |   {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 126 |     if (!eq(src, dst)) {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 127 | val in = new FileInputStream(src) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 128 |       try {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 129 | val out = new FileOutputStream(dst) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 130 |         try {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 131 | val buf = new Array[Byte](65536) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 132 | var m = 0 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 133 |           do {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 134 | m = in.read(buf, 0, buf.length) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 135 | if (m != -1) out.write(buf, 0, m) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 136 | } while (m != -1) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 137 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 138 |         finally { out.close }
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 139 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 140 |       finally { in.close }
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 141 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 142 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 143 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 144 | def copy(path1: Path, path2: Path): Unit = copy(path1.file, path2.file) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 145 | |
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 146 | |
| 48613 
232652ac346e
clarified directory content operations (similar to ML version);
 wenzelm parents: 
48550diff
changeset | 147 | /* tmp files */ | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 148 | |
| 48418 | 149 | def tmp_file(prefix: String): JFile = | 
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 150 |   {
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 151 | val file = JFile.createTempFile(prefix, null) | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 152 | file.deleteOnExit | 
| 48418 | 153 | file | 
| 154 | } | |
| 155 | ||
| 156 | def with_tmp_file[A](prefix: String)(body: JFile => A): A = | |
| 157 |   {
 | |
| 158 | val file = tmp_file(prefix) | |
| 48411 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 159 |     try { body(file) } finally { file.delete }
 | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 160 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 161 | } | 
| 
5b3440850d36
more abstract file system operations in Scala, corresponding to ML version;
 wenzelm parents: diff
changeset | 162 |