moved files extensions into a Files.kt and added File.forEachLine for easier iterating through a file in lines
This commit is contained in:
@@ -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<FileInputStream,ByteArray>{ 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<FileOutputStream,Unit>{ 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<FileInputStream,Long>{
|
||||||
|
val output = FileOutputStream(file)
|
||||||
|
output.use<FileOutputStream,Long>{
|
||||||
|
input.copyTo(output, bufferSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -209,7 +209,9 @@ public inline fun Writer.buffered(bufferSize: Int = defaultBufferSize): Buffered
|
|||||||
= if(this is BufferedWriter) this else BufferedWriter(this, bufferSize)
|
= 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 {
|
public inline fun Reader.forEachLine(block: (String) -> Unit): Unit {
|
||||||
this.use{
|
this.use{
|
||||||
val iter = buffered().lineIterator()
|
val iter = buffered().lineIterator()
|
||||||
@@ -257,137 +259,6 @@ class LineIterator(val reader: BufferedReader) : Iterator<String> {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<FileInputStream,ByteArray>{ 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<FileOutputStream,Unit>{ 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<FileInputStream,Long>{
|
|
||||||
val output = FileOutputStream(file)
|
|
||||||
output.use<FileOutputStream,Long>{
|
|
||||||
input.copyTo(output, bufferSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads this stream completely into a byte array
|
* Reads this stream completely into a byte array
|
||||||
|
|||||||
Reference in New Issue
Block a user