more IO API documentation

This commit is contained in:
Mark Harrah 2012-01-26 21:28:19 -05:00
parent f55d34f617
commit d82757f595
1 changed files with 58 additions and 7 deletions

View File

@ -17,6 +17,7 @@ import scala.collection.mutable.{HashMap,HashSet}
import scala.reflect.{Manifest => SManifest}
import Function.tupled
/** A collection of File, URL, and I/O utility methods.*/
object IO
{
/** The maximum number of times a unique temporary filename is attempted to be created.*/
@ -26,21 +27,40 @@ object IO
val temporaryDirectory = new File(System.getProperty("java.io.tmpdir"))
/** The size of the byte or char buffer used in various methods.*/
private val BufferSize = 8192
/** The newline string for this system, as obtained by the line.separator system property. */
val Newline = System.getProperty("line.separator")
val utf8 = Charset.forName("UTF-8")
/** Returns a URL for the directory or jar containing the the class file `cl`.
* If the location cannot be determined, an error is generated.
* Note that Java standard library classes typically do not have a location associated with them.*/
def classLocation(cl: Class[_]): URL =
{
val codeSource = cl.getProtectionDomain.getCodeSource
if(codeSource == null) error("No class location for " + cl)
else codeSource.getLocation
}
/** Returns the directory or jar file containing the the class file `cl`.
* If the location cannot be determined or it is not a file, an error is generated.
* Note that Java standard library classes typically do not have a location associated with them.*/
def classLocationFile(cl: Class[_]): File = toFile(classLocation(cl))
/** Returns a URL for the directory or jar containing the class file for type `T` (as determined by an implicit Manifest).
* If the location cannot be determined, an error is generated.
* Note that Java standard library classes typically do not have a location associated with them.*/
def classLocation[T](implicit mf: SManifest[T]): URL = classLocation(mf.erasure)
/** Returns the directory or jar file containing the the class file for type `T` (as determined by an implicit Manifest).
* If the location cannot be determined, an error is generated.
* Note that Java standard library classes typically do not have a location associated with them.*/
def classLocationFile[T](implicit mf: SManifest[T]): File = classLocationFile(mf.erasure)
def toFile(url: URL) =
/** Constructs a File corresponding to `url`, which must have a scheme of `file`.
* This method properly works around an issue with a simple conversion to URI and then to a File. */
def toFile(url: URL): File =
try { new File(url.toURI) }
catch { case _: URISyntaxException => new File(url.getPath) }
@ -61,6 +81,13 @@ object IO
def assertDirectories(file: File*) { file.foreach(assertDirectory) }
// "base.extension" -> (base, extension)
/** Splits the given string into base and extension strings.
* If `name` contains no period, the base string is the input string and the extension is the empty string.
* Otherwise, the base is the substring up until the last period (exclusive) and
* the extension is the substring after the last period.
*
* For example, `split("Build.scala") == ("Build", "scala")`
*/
def split(name: String): (String, String) =
{
val lastDot = name.lastIndexOf('.')
@ -70,8 +97,13 @@ object IO
(name, "")
}
/** Each input file in `files` is created if it doesn't exist.
* If a file already exists, the last modified time is set to the current time.
* It is not guaranteed that all files will have the same last modified time after this call.*/
def touch(files: Traversable[File]): Unit = files.foreach(f => touch(f))
/** Creates a file at the given location.*/
/** Creates a file at the given location if it doesn't exist.
* If the file already exists and `setModified` is true, this method sets the last modified time to the current time.*/
def touch(file: File, setModified: Boolean = true)
{
val absFile = file.getAbsoluteFile
@ -178,13 +210,16 @@ object IO
transfer(inputStream, to)
}
/** Copies the contents of `in` to `out`.*/
def transfer(in: File, out: File): Unit =
fileInputStream(in){ in => transfer(in, out) }
/** Copies the contents of the input file `in` to the `out` stream.
* The output stream is not closed by this method.*/
def transfer(in: File, out: OutputStream): Unit =
fileInputStream(in){ in => transfer(in, out) }
/** Copies all bytes from the given input stream to the given File.*/
/** Copies all bytes from the given input stream to the given File. The input stream is not closed by this method.*/
def transfer(in: InputStream, to: File): Unit =
Using.fileOutputStream()(to) { outputStream =>
transfer(in, outputStream)
@ -223,7 +258,11 @@ object IO
try { action(dir) }
finally { delete(dir) }
}
/** Creates a directory in the default temporary directory with a name generated from a random integer. */
def createTemporaryDirectory: File = createUniqueDirectory(temporaryDirectory)
/** Creates a directory in `baseDirectory` with a name generated from a random integer */
def createUniqueDirectory(baseDirectory: File): File =
{
def create(tries: Int): File =
@ -241,6 +280,8 @@ object IO
}
create(0)
}
/** Creates a file in the default temporary directory, calls `action` with the file, deletes the file, and returns the result of calling `action`.
* The name of the file will begin with `prefix`, which must be at least three characters long, and end with `postfix`, which has no minimum length. */
def withTemporaryFile[T](prefix: String, postfix: String)(action: File => T): T =
{
val file = File.createTempFile(prefix, postfix)
@ -250,6 +291,7 @@ object IO
private[sbt] def jars(dir: File): Iterable[File] = listFiles(dir, GlobFilter("*.jar"))
/** Deletes all empty directories in the set. Any non-empty directories are ignored. */
def deleteIfEmpty(dirs: collection.Set[File]): Unit =
{
val isEmpty = new HashMap[File, Boolean]
@ -259,7 +301,10 @@ object IO
for( (f, true) <- isEmpty) f.delete
}
/** Deletes each file or directory (recursively) in `files`.*/
def delete(files: Iterable[File]): Unit = files.foreach(delete)
/** Deletes `file`, recursively if it is a directory. */
def delete(file: File)
{
translate("Error deleting file " + file + ": ")
@ -273,26 +318,32 @@ object IO
file.delete
}
}
/** Returns the children of directory `dir` that match `filter` in a non-null array.*/
def listFiles(filter: java.io.FileFilter)(dir: File): Array[File] = wrapNull(dir.listFiles(filter))
/** Returns the children of directory `dir` that match `filter` in a non-null array.*/
def listFiles(dir: File, filter: java.io.FileFilter): Array[File] = wrapNull(dir.listFiles(filter))
/** Returns the children of directory `dir` in a non-null array.*/
def listFiles(dir: File): Array[File] = wrapNull(dir.listFiles())
private[sbt] def wrapNull(a: Array[File]) =
{
if(a == null)
new Array[File](0)
else
a
}
/** Creates a jar file.
* @param sources The files to include in the jar file paired with the entry name in the jar.
* @param sources The files to include in the jar file paired with the entry name in the jar. Only the pairs explicitly listed are included.
* @param outputJar The file to write the jar to.
* @param manifest The manifest for the jar.*/
def jar(sources: Traversable[(File,String)], outputJar: File, manifest: Manifest): Unit =
archive(sources.toSeq, outputJar, Some(manifest))
/** Creates a zip file.
* @param sources The files to include in the zip file paired with the entry name in the zip.
* @param sources The files to include in the zip file paired with the entry name in the zip. Only the pairs explicitly listed are included.
* @param outputZip The file to write the zip to.*/
def zip(sources: Traversable[(File,String)], outputZip: File): Unit =
archive(sources.toSeq, outputZip, None)