From e2af3bae28c6be31b315bfb3d8a2a7778d6b5c95 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 18 Apr 2012 08:38:15 +0100 Subject: [PATCH] moved files extensions into a Files.kt and added File.forEachLine for easier iterating through a file in lines --- libraries/stdlib/src/kotlin/io/Files.kt | 149 ++++++++++++++++++++++++ libraries/stdlib/src/kotlin/io/JIO.kt | 135 +-------------------- 2 files changed, 152 insertions(+), 132 deletions(-) create mode 100644 libraries/stdlib/src/kotlin/io/Files.kt diff --git a/libraries/stdlib/src/kotlin/io/Files.kt b/libraries/stdlib/src/kotlin/io/Files.kt new file mode 100644 index 00000000000..960c9093b59 --- /dev/null +++ b/libraries/stdlib/src/kotlin/io/Files.kt @@ -0,0 +1,149 @@ +package kotlin.io + +import java.io.* +import java.nio.charset.* +import java.util.NoSuchElementException +import java.net.URL + + +/** + * Recursively process this file and all children with the given block + */ +public fun File.recurse(block: (File) -> Unit): Unit { + block(this) + if (this.isDirectory()) { + for (child in this.listFiles()) { + if (child != null) { + child.recurse(block) + } + } + } +} + +/** + * Returns this if the file is a directory or the parent if its a file inside a directory + */ +inline val File.directory: File +get() = if (this.isDirectory()) this else this.getParentFile().sure() + +/** + * Returns the canoncial path of the file + */ +inline val File.canonicalPath: String +get() = getCanonicalPath() ?: "" + +/** + * Returns the file name or "" for an empty name + */ +inline val File.name: String +get() = getName() ?: "" + +/** + * Returns the file path or "" for an empty name + */ +inline val File.path: String +get() = getPath() ?: "" + +/** + * Returns true if the file ends with the given extension + */ +inline val File.extension: String +get() { + val text = this.name + val idx = text.lastIndexOf('.') + return if (idx >= 0) { + text.substring(idx + 1) + } else { + "" + } +} + +/** +* Returns true if the given file is in the same directory or a descendant directory +*/ +public fun File.isDescendant(file: File): Boolean { + return file.directory.canonicalPath.startsWith(this.directory.canonicalPath) +} + +/** + * Returns the relative path of the given descendant of this file if its a descendant + */ +public fun File.relativePath(descendant: File): String { + val prefix = this.directory.canonicalPath + val answer = descendant.canonicalPath + return if (answer.startsWith(prefix)) { + answer.substring(prefix.size + 1) + } else { + answer + } +} + +/** + * Creates a new [[FileReader]] for this file + */ +public inline fun File.reader(): FileReader = FileReader(this) + +/** + * Iterates through each line of this file then closing the underlying [[Reader]] when its completed + */ +public inline fun File.forEachLine(block: (String) -> Unit): Unit = reader().forEachLine(block) + +/** + * Reads the entire content of the file as bytes + * + * This method is not recommended on huge files. + */ +public fun File.readBytes(): ByteArray { + return FileInputStream(this).use{ it.readBytes(this.length().toInt()) } +} + +/** + * Writes the bytes as the contents of the file + */ +public fun File.writeBytes(data: ByteArray): Unit { + return FileOutputStream(this).use{ it.write(data) } +} +/** + * Reads the entire content of the file as a String using the optional + * character encoding. The default platform encoding is used if the character + * encoding is not specified or null. + * + * This method is not recommended on huge files. + */ +public fun File.readText(encoding:String? = null) : String = readBytes().toString(encoding) + +/** + * Reads the entire content of the file as a String using the + * character encoding. + * + * This method is not recommended on huge files. + */ +public fun File.readText(encoding:Charset) : String = readBytes().toString(encoding) + +/** + * Writes the text as the contents of the file using the optional + * character encoding. The default platform encoding is used if the character + * encoding is not specified or null. + */ +public fun File.writeText(text: String, encoding:String?=null): Unit { writeBytes(text.toByteArray(encoding)) } + +/** + * Writes the text as the contents of the file using the optional + * character encoding. The default platform encoding is used if the character + * encoding is not specified or null. + */ +public fun File.writeText(text: String, encoding:Charset): Unit { writeBytes(text.toByteArray(encoding)) } + +/** + * Copies this file to the given output file, returning the number of bytes copied + */ +public fun File.copyTo(file: File, bufferSize: Int = defaultBufferSize): Long { + file.directory.mkdirs() + val input = FileInputStream(this) + return input.use{ + val output = FileOutputStream(file) + output.use{ + input.copyTo(output, bufferSize) + } + } +} diff --git a/libraries/stdlib/src/kotlin/io/JIO.kt b/libraries/stdlib/src/kotlin/io/JIO.kt index 559ba8ed130..841f65d6ff7 100644 --- a/libraries/stdlib/src/kotlin/io/JIO.kt +++ b/libraries/stdlib/src/kotlin/io/JIO.kt @@ -209,7 +209,9 @@ public inline fun Writer.buffered(bufferSize: Int = defaultBufferSize): Buffered = if(this is BufferedWriter) this else BufferedWriter(this, bufferSize) - +/** + * Iterates through each line of this reader then closing the [[Reader]] when its completed + */ public inline fun Reader.forEachLine(block: (String) -> Unit): Unit { this.use{ val iter = buffered().lineIterator() @@ -257,137 +259,6 @@ class LineIterator(val reader: BufferedReader) : Iterator { -/** - * Recursively process this file and all children with the given block - */ -public fun File.recurse(block: (File) -> Unit): Unit { - block(this) - if (this.isDirectory()) { - for (child in this.listFiles()) { - if (child != null) { - child.recurse(block) - } - } - } -} - -/** - * Returns this if the file is a directory or the parent if its a file inside a directory - */ -inline val File.directory: File -get() = if (this.isDirectory()) this else this.getParentFile().sure() - -/** - * Returns the canoncial path of the file - */ -inline val File.canonicalPath: String -get() = getCanonicalPath() ?: "" - -/** - * Returns the file name or "" for an empty name - */ -inline val File.name: String -get() = getName() ?: "" - -/** - * Returns the file path or "" for an empty name - */ -inline val File.path: String -get() = getPath() ?: "" - -/** - * Returns true if the file ends with the given extension - */ -inline val File.extension: String -get() { - val text = this.name - val idx = text.lastIndexOf('.') - return if (idx >= 0) { - text.substring(idx + 1) - } else { - "" - } -} - -/** -* Returns true if the given file is in the same directory or a descendant directory -*/ -public fun File.isDescendant(file: File): Boolean { - return file.directory.canonicalPath.startsWith(this.directory.canonicalPath) -} - -/** - * Returns the relative path of the given descendant of this file if its a descendant - */ -public fun File.relativePath(descendant: File): String { - val prefix = this.directory.canonicalPath - val answer = descendant.canonicalPath - return if (answer.startsWith(prefix)) { - answer.substring(prefix.size + 1) - } else { - answer - } -} - -/** - * Reads the entire content of the file as bytes - * - * This method is not recommended on huge files. - */ -public fun File.readBytes(): ByteArray { - return FileInputStream(this).use{ it.readBytes(this.length().toInt()) } -} - -/** - * Writes the bytes as the contents of the file - */ -public fun File.writeBytes(data: ByteArray): Unit { - return FileOutputStream(this).use{ it.write(data) } -} -/** - * Reads the entire content of the file as a String using the optional - * character encoding. The default platform encoding is used if the character - * encoding is not specified or null. - * - * This method is not recommended on huge files. - */ -public fun File.readText(encoding:String? = null) : String = readBytes().toString(encoding) - -/** - * Reads the entire content of the file as a String using the - * character encoding. - * - * This method is not recommended on huge files. - */ -public fun File.readText(encoding:Charset) : String = readBytes().toString(encoding) - -/** - * Writes the text as the contents of the file using the optional - * character encoding. The default platform encoding is used if the character - * encoding is not specified or null. - */ -public fun File.writeText(text: String, encoding:String?=null): Unit { writeBytes(text.toByteArray(encoding)) } - -/** - * Writes the text as the contents of the file using the optional - * character encoding. The default platform encoding is used if the character - * encoding is not specified or null. - */ -public fun File.writeText(text: String, encoding:Charset): Unit { writeBytes(text.toByteArray(encoding)) } - -/** - * Copies this file to the given output file, returning the number of bytes copied - */ -public fun File.copyTo(file: File, bufferSize: Int = defaultBufferSize): Long { - file.directory.mkdirs() - val input = FileInputStream(this) - return input.use{ - val output = FileOutputStream(file) - output.use{ - input.copyTo(output, bufferSize) - } - } -} /** * Reads this stream completely into a byte array