Implement additional Path extensions
#KT-19192
This commit is contained in:
@@ -18,6 +18,9 @@ import java.nio.file.StandardOpenOption
|
||||
|
||||
/**
|
||||
* Returns a new [InputStreamReader] for reading the content of this file.
|
||||
*
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @param options options to determine how the file is opened.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -29,9 +32,9 @@ public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options:
|
||||
/**
|
||||
* Returns a new [BufferedReader] for reading the content of this file.
|
||||
*
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @param bufferSize necessary size of the buffer.
|
||||
* @param options options to determine how the file is opened
|
||||
* @param options options to determine how the file is opened.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -46,6 +49,9 @@ public inline fun Path.bufferedReader(
|
||||
|
||||
/**
|
||||
* Returns a new [OutputStreamWriter] for writing the content of this file.
|
||||
*
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
* @param options options to determine how the file is opened.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -57,7 +63,7 @@ public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options:
|
||||
/**
|
||||
* Returns a new [BufferedWriter] for writing the content of this file.
|
||||
*
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
* @param bufferSize necessary size of the buffer.
|
||||
* @param options options to determine how the file is opened.
|
||||
*/
|
||||
@@ -87,7 +93,7 @@ public inline fun Path.readBytes(): ByteArray {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an [array] of bytes to this file.
|
||||
* Writes an [array] of bytes to this file.
|
||||
*
|
||||
* By default, the file will be overwritten if it already exists, but you can control this behavior
|
||||
* with [options].
|
||||
@@ -110,30 +116,33 @@ public inline fun Path.writeBytes(array: ByteArray, vararg options: OpenOption):
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.appendBytes(array: ByteArray): Unit {
|
||||
writeBytes(array, StandardOpenOption.APPEND)
|
||||
public inline fun Path.appendBytes(array: ByteArray) {
|
||||
Files.write(this, array, StandardOpenOption.APPEND)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entire content of this file as a String using UTF-8 or specified [charset].
|
||||
* Gets the entire content of this file as a String using UTF-8 or the specified [charset].
|
||||
*
|
||||
* This method is not recommended on huge files. It has an internal limitation of 2 GB file size.
|
||||
*
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @return the entire content of this file as a String.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset)
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String =
|
||||
readBytes().toString(charset)
|
||||
|
||||
/**
|
||||
* Sets the content of this file as [text] encoded using UTF-8 or specified [charset].
|
||||
* Sets the content of this file as [text] encoded using UTF-8 or the specified [charset].
|
||||
*
|
||||
* By default, the file will be overwritten if it already exists, but you can control this behavior
|
||||
* with [options].
|
||||
*
|
||||
* @param text text to write into file.
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
* @param options options to determine how the file is opened.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -145,7 +154,7 @@ public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, varar
|
||||
* Appends [text] to the content of this file using UTF-8 or the specified [charset].
|
||||
*
|
||||
* @param text text to append to file.
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -160,7 +169,7 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni
|
||||
* You may use this function on huge files.
|
||||
*
|
||||
* @param options options to determine how the file is opened.
|
||||
* @param charset character set to use.
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @param action function to process file lines.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@@ -203,7 +212,7 @@ public inline fun Path.outputStream(vararg options: OpenOption): OutputStream {
|
||||
*
|
||||
* Do not use this function for huge files.
|
||||
*
|
||||
* @param charset character set to use. By default uses UTF-8 charset.
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @return list of file lines.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@@ -217,7 +226,7 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List<String
|
||||
* Calls the [block] callback giving it a sequence of all the lines in this file and closes the reader once
|
||||
* the processing is complete.
|
||||
|
||||
* @param charset character set to use. By default uses UTF-8 charset.
|
||||
* @param charset character set to use for reading text, UTF-8 by default.
|
||||
* @return the value returned by [block].
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@@ -226,3 +235,59 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List<String
|
||||
public inline fun <T> Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T {
|
||||
return bufferedReader(charset).use { block(it.lineSequence()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the specified collection of char sequences [lines] to a file terminating each one with the platform's line separator.
|
||||
*
|
||||
* By default, the file will be overwritten if it already exists, but you can control this behavior
|
||||
* with [options].
|
||||
*
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.writeLines(lines: Iterable<CharSequence>, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Path {
|
||||
return Files.write(this, lines, charset, *options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the specified sequence of char sequences [lines] to a file terminating each one with the platform's line separator.
|
||||
*
|
||||
* By default, the file will be overwritten if it already exists, but you can control this behavior
|
||||
* with [options].
|
||||
*
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.writeLines(lines: Sequence<CharSequence>, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Path {
|
||||
return Files.write(this, lines.asIterable(), charset, *options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified collection of char sequences [lines] to a file terminating each one with the platform's line separator.
|
||||
*
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.appendLines(lines: Iterable<CharSequence>, charset: Charset = Charsets.UTF_8): Path {
|
||||
return Files.write(this, lines, charset, StandardOpenOption.APPEND)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified sequence of char sequences [lines] to a file terminating each one with the platform's line separator.
|
||||
*
|
||||
* @param charset character set to use for writing text, UTF-8 by default.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.appendLines(lines: Sequence<CharSequence>, charset: Charset = Charsets.UTF_8): Path {
|
||||
return Files.write(this, lines.asIterable(), charset, StandardOpenOption.APPEND)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,33 @@
|
||||
package kotlin.io.path
|
||||
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
import java.nio.file.*
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.NoSuchFileException
|
||||
import java.nio.file.attribute.*
|
||||
|
||||
/**
|
||||
* Returns the extension of this path (not including the dot), or an empty string if it doesn't have one.
|
||||
* Returns the name of the file or directory denoted by this path as a string,
|
||||
* or an empty string if this path has zero path elements.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public val Path.name: String
|
||||
get() = fileName?.toString().orEmpty()
|
||||
|
||||
/**
|
||||
* Returns the [name][Path.name] of this file or directory without an extension,
|
||||
* or an empty string if this path has zero path elements.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public val Path.nameWithoutExtension: String
|
||||
get() = fileName?.toString()?.substringBeforeLast(".") ?: ""
|
||||
|
||||
/**
|
||||
* Returns the extension of this path (not including the dot),
|
||||
* or an empty string if it doesn't have one.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -34,21 +55,14 @@ public val Path.invariantSeparatorsPath: String
|
||||
return if (separator != "/") toString().replace(separator, "/") else toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this path's [fileName][Path.getFileName] without an extension, or an empty string if
|
||||
* this path has zero elements.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public val Path.nameWithoutExtension: String
|
||||
get() = fileName?.toString()?.substringBeforeLast(".") ?: ""
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this path from a [base] path.
|
||||
*
|
||||
* Note that the [base] path is treated as a directory.
|
||||
* If this path matches the [base] path, then a [Path] with an empty path will be returned.
|
||||
*
|
||||
* @return Path with relative path from [base] to this.
|
||||
* @return the relative path from [base] to this.
|
||||
*
|
||||
* @throws IllegalArgumentException if this and base paths have different roots.
|
||||
*/
|
||||
@@ -57,15 +71,16 @@ public val Path.nameWithoutExtension: String
|
||||
public fun Path.relativeTo(base: Path): Path = try {
|
||||
PathRelativizer.tryRelativeTo(this, base)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw java.lang.IllegalArgumentException(e.message + "\nthis path: $this\nbase path: $base", e)
|
||||
throw IllegalArgumentException(e.message + "\nthis path: $this\nbase path: $base", e)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this path from a [base] path.
|
||||
*
|
||||
* Note that the [base] path is treated as a directory.
|
||||
* If this path matches the [base] path, then a [Path] with an empty path will be returned.
|
||||
*
|
||||
* @return Path with relative path from [base] to this, or `this` if this and base paths have different roots.
|
||||
* @return the relative path from [base] to this, or `this` if this and base paths have different roots.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -74,10 +89,11 @@ public fun Path.relativeToOrSelf(base: Path): Path =
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this path from a [base] path.
|
||||
*
|
||||
* Note that the [base] path is treated as a directory.
|
||||
* If this path matches the [base] path, then a [Path] with an empty path will be returned.
|
||||
*
|
||||
* @return Path with relative path from [base] to this, or `null` if this and base paths have different roots.
|
||||
* @return the relative path from [base] to this, or `null` if this and base paths have different roots.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -87,7 +103,7 @@ public fun Path.relativeToOrNull(base: Path): Path? = try {
|
||||
null
|
||||
}
|
||||
|
||||
internal object PathRelativizer {
|
||||
private object PathRelativizer {
|
||||
private val emptyPath = Paths.get("")
|
||||
private val parentPath = Paths.get("..")
|
||||
|
||||
@@ -117,9 +133,9 @@ internal object PathRelativizer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies this path to the given [target] path.
|
||||
* Copies a file or directory located by this path to the given [target] path.
|
||||
*
|
||||
* Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically.
|
||||
* Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() })
|
||||
@@ -141,18 +157,21 @@ internal object PathRelativizer {
|
||||
* @throws DirectoryNotEmptyException if the destination path point to an existing directory and [overwrite] argument is `true`,
|
||||
* when the directory being replaced is not empty.
|
||||
* @throws IOException if any errors occur while copying.
|
||||
*
|
||||
* @see Files.copy
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path {
|
||||
val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray()
|
||||
return copyTo(target, *options)
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.copyTo(target: Path, overwrite: Boolean = false): Path {
|
||||
val options = if (overwrite) arrayOf<CopyOption>(StandardCopyOption.REPLACE_EXISTING) else emptyArray()
|
||||
return Files.copy(this, target, *options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies this path to the given [target] path.
|
||||
* Copies a file or directory located by this path to the given [target] path.
|
||||
*
|
||||
* Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically.
|
||||
* Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() })
|
||||
@@ -177,17 +196,25 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path {
|
||||
* @throws DirectoryNotEmptyException if the destination path point to an existing directory and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used,
|
||||
* when the directory being replaced is not empty.
|
||||
* @throws IOException if any errors occur while copying.
|
||||
*
|
||||
* @see Files.copy
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public fun Path.copyTo(target: Path, vararg options: CopyOption): Path {
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.copyTo(target: Path, vararg options: CopyOption): Path {
|
||||
return Files.copy(this, target, *options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this path exists.
|
||||
* Checks if the file located by this path exists.
|
||||
*
|
||||
* @param options Options to control how symbolic links are handled.
|
||||
* @return `true`, if the file definitely exists, `false` otherwise,
|
||||
* including situations when the existence cannot be determined.
|
||||
*
|
||||
* @param options options to control how symbolic links are handled.
|
||||
*
|
||||
* @see Files.exists
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -195,9 +222,14 @@ public fun Path.copyTo(target: Path, vararg options: CopyOption): Path {
|
||||
public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options)
|
||||
|
||||
/**
|
||||
* Check if this path does not exist.
|
||||
* Checks if the file located by this path does not exist.
|
||||
*
|
||||
* @param options Options to control how symbolic links are handled.
|
||||
* @return `true`, if the file definitely does not exist, `false` otherwise,
|
||||
* including situations when the existence cannot be determined.
|
||||
*
|
||||
* @param options options to control how symbolic links are handled.
|
||||
*
|
||||
* @see Files.notExists
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -205,9 +237,11 @@ public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exist
|
||||
public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.notExists(this, *options)
|
||||
|
||||
/**
|
||||
* Check if this path is a file.
|
||||
* Checks if the file located by this path is a regular file.
|
||||
*
|
||||
* @param options Options to control how symbolic links are handled.
|
||||
* @param options options to control how symbolic links are handled.
|
||||
*
|
||||
* @see Files.isRegularFile
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -215,11 +249,13 @@ public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.no
|
||||
public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options)
|
||||
|
||||
/**
|
||||
* Check if this path is a directory.
|
||||
* Checks if the file located by this path is a directory.
|
||||
*
|
||||
* By default, symbolic links in the path are followed.
|
||||
*
|
||||
* @param options Options to control how symbolic links are handled.
|
||||
* @param options options to control how symbolic links are handled.
|
||||
*
|
||||
* @see Files.isDirectory
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -227,7 +263,9 @@ public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = File
|
||||
public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options)
|
||||
|
||||
/**
|
||||
* Check if this path exists and is a symbolic link.
|
||||
* Checks if the file located by this path exists and is a symbolic link.
|
||||
*
|
||||
* @see Files.isSymbolicLink
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -235,7 +273,9 @@ public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.
|
||||
public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this)
|
||||
|
||||
/**
|
||||
* Check if this path exists and is executable.
|
||||
* Checks if the file located by this path exists and is executable.
|
||||
*
|
||||
* @see Files.isExecutable
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -243,10 +283,12 @@ public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this)
|
||||
public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this)
|
||||
|
||||
/**
|
||||
* Check if this path is considered hidden.
|
||||
* Checks if the file located by this path is considered hidden.
|
||||
*
|
||||
* This check is dependant on the current filesystem. For example, on UNIX-like operating systems, a
|
||||
* path is considered hidden if its name begins with a dot. On Windows, file attributes are checked.
|
||||
*
|
||||
* @see Files.isHidden
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -254,7 +296,9 @@ public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this)
|
||||
public inline fun Path.isHidden(): Boolean = Files.isHidden(this)
|
||||
|
||||
/**
|
||||
* Check if this path exists and is readable.
|
||||
* Checks if the file located by this path exists and is readable.
|
||||
*
|
||||
* @see Files.isReadable
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -262,7 +306,9 @@ public inline fun Path.isHidden(): Boolean = Files.isHidden(this)
|
||||
public inline fun Path.isReadable(): Boolean = Files.isReadable(this)
|
||||
|
||||
/**
|
||||
* Check that this path exists and is writable.
|
||||
* Checks if the file located by this path exists and is writable.
|
||||
*
|
||||
* @see Files.isWritable
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@@ -270,21 +316,23 @@ public inline fun Path.isReadable(): Boolean = Files.isReadable(this)
|
||||
public inline fun Path.isWritable(): Boolean = Files.isWritable(this)
|
||||
|
||||
/**
|
||||
* Check if this path points to the same file or directory as [other].
|
||||
* Checks if the file located by this path points to the same file or directory as [other].
|
||||
*
|
||||
* @see Files.isSameFile
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other)
|
||||
public inline fun Path.isSameFileAs(other: Path): Boolean = Files.isSameFile(this, other)
|
||||
|
||||
/**
|
||||
* Return a list of the entries in this directory optionally filtered by matching against the specified [glob] pattern.
|
||||
* Returns a list of the entries in this directory optionally filtered by matching against the specified [glob] pattern.
|
||||
*
|
||||
* @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method.
|
||||
*
|
||||
* @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid.
|
||||
* @throws NotDirectoryException If this path does not refer to a directory
|
||||
* @throws IOException If an I/O error occurs
|
||||
* @throws NotDirectoryException If this path does not refer to a directory.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*
|
||||
* @see Files.newDirectoryStream
|
||||
*/
|
||||
@@ -295,37 +343,564 @@ public fun Path.listDirectoryEntries(glob: String = "*"): List<Path> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the [block] callback with a sequence of all entries in this directory
|
||||
* Calls the [block] callback with a sequence of all entries in this directory
|
||||
* optionally filtered by matching against the specified [glob] pattern.
|
||||
*
|
||||
* @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method.
|
||||
*
|
||||
* @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid.
|
||||
* @throws NotDirectoryException If this path does not refer to a directory
|
||||
* @throws IOException If an I/O error occurs
|
||||
* @return the value returned by [block]
|
||||
* @throws NotDirectoryException If this path does not refer to a directory.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
* @return the value returned by [block].
|
||||
*
|
||||
* @see Files.newDirectoryStream
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public fun <T> Path.useDirectoryEntries(glob: String = "*", block: (Sequence<Path>) -> T): T {
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> Path.useDirectoryEntries(glob: String = "*", block: (Sequence<Path>) -> T): T {
|
||||
return Files.newDirectoryStream(this, glob).use { block(it.asSequence()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the given [action] on each entry in this directory optionally filtered by matching against the specified [glob] pattern.
|
||||
* Performs the given [action] on each entry in this directory optionally filtered by matching against the specified [glob] pattern.
|
||||
*
|
||||
* @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method.
|
||||
*
|
||||
* @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid.
|
||||
* @throws NotDirectoryException If this path does not refer to a directory
|
||||
* @throws IOException If an I/O error occurs
|
||||
* @throws NotDirectoryException If this path does not refer to a directory.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*
|
||||
* @see Files.newDirectoryStream
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
public fun Path.forEachDirectoryEntry(glob: String = "*", action: (Path) -> Unit) {
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.forEachDirectoryEntry(glob: String = "*", action: (Path) -> Unit) {
|
||||
return Files.newDirectoryStream(this, glob).use { it.forEach(action) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a regular file as a [Long] value of bytes or throws an exception if the file doesn't exist.
|
||||
*
|
||||
* @throws IOException if an I/O error occurred.
|
||||
* @see Files.size
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.fileSize(): Long =
|
||||
Files.size(this)
|
||||
|
||||
/**
|
||||
* Deletes the existing file or empty directory specified by this path.
|
||||
*
|
||||
* @throws NoSuchFileException if the file or directory does not exist.
|
||||
* @throws DirectoryNotEmptyException if the directory exists but is not empty.
|
||||
*
|
||||
* @see Files.delete
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.deleteExisting() {
|
||||
Files.delete(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the file or empty directory specified by this path if it exists.
|
||||
*
|
||||
* @return `true` if the existing file was successfully deleted, `false` if the file does not exist.
|
||||
*
|
||||
* @throws DirectoryNotEmptyException if the directory exists but is not empty
|
||||
*
|
||||
* @see Files.deleteIfExists
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.deleteIfExists() =
|
||||
Files.deleteIfExists(this)
|
||||
|
||||
/**
|
||||
* Creates a new directory or throws an exception if there is already a file or directory located by this path.
|
||||
*
|
||||
* Note that the parent directory where this directory is going to be created must already exist.
|
||||
* If you need to create all non-existent parent directories, use [Path.createDirectories].
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the directory.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if there is already a file or directory located by this path
|
||||
* (optional specific exception, some implementations may throw more general [IOException]).
|
||||
* @throws IOException if an I/O error occurs or the parent directory does not exist.
|
||||
* @throws UnsupportedOperationException if the [attributes ]array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createDirectory
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.createDirectory(vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createDirectory(this, *attributes)
|
||||
|
||||
/**
|
||||
* Creates a directory ensuring that all nonexistent parent directories exist by creating them first.
|
||||
*
|
||||
* If the directory already exists, this function does not throw an exception, unlike [Path.createDirectory].
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the directory.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if there is already a file located by this path
|
||||
* (optional specific exception, some implementations may throw more general [IOException]).
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws UnsupportedOperationException if the [attributes ]array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createDirectories
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.createDirectories(vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createDirectories(this, *attributes)
|
||||
|
||||
|
||||
/**
|
||||
* Moves or renames the file located by this path to the [target] path.
|
||||
*
|
||||
* @param options options specifying how the move should be done, see [StandardCopyOption], [LinkOption].
|
||||
*
|
||||
* @throws FileAlreadyExistsException if the target file exists but cannot be replaced because the
|
||||
* [StandardCopyOption.REPLACE_EXISTING] option is not specified (optional specific exception).
|
||||
* @throws DirectoryNotEmptyException the [StandardCopyOption.REPLACE_EXISTING] option is specified but the file
|
||||
* cannot be replaced because it is a non-empty directory, or the
|
||||
* source is a non-empty directory containing entries that would
|
||||
* be required to be moved (optional specific exception).
|
||||
*
|
||||
* @see Files.move
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.moveTo(target: Path, vararg options: CopyOption): Path =
|
||||
Files.move(this, target, *options)
|
||||
|
||||
/**
|
||||
* Moves or renames the file located by this path to the [target] path.
|
||||
*
|
||||
* @param overwrite allows to overwrite the target if it already exists.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if the target file exists but cannot be replaced because the
|
||||
* `overwrite = true` option is not specified (optional specific exception).
|
||||
* @throws DirectoryNotEmptyException the `overwrite = true` option is specified but the file
|
||||
* cannot be replaced because it is a non-empty directory, or the
|
||||
* source is a non-empty directory containing entries that would
|
||||
* be required to be moved (optional specific exception).
|
||||
*
|
||||
* @see Files.move
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.moveTo(target: Path, overwrite: Boolean = false): Path {
|
||||
val options = if (overwrite) arrayOf<CopyOption>(StandardCopyOption.REPLACE_EXISTING) else emptyArray()
|
||||
return Files.move(this, target, *options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [FileStore] representing the file store where a file is located.
|
||||
*
|
||||
* @see Files.getFileStore
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.fileStore(): FileStore =
|
||||
Files.getFileStore(this)
|
||||
|
||||
/**
|
||||
* Reads the value of a file attribute.
|
||||
*
|
||||
* The attribute name is specified with the [attribute] parameter optionally prefixed with the attribute view name:
|
||||
* ```
|
||||
* [view_name:]attribute_name
|
||||
* ```
|
||||
* When the view name is not specified, it defaults to `basic`.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the attribute view is not supported.
|
||||
* @throws IllegalArgumentException if the attribute name is not specified or is not recognized.
|
||||
* @see Files.getAttribute
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.getAttribute(attribute: String, vararg options: LinkOption): Any? =
|
||||
Files.getAttribute(this, attribute, *options)
|
||||
|
||||
/**
|
||||
* Sets the value of a file attribute.
|
||||
*
|
||||
* The attribute name is specified with the [attribute] parameter optionally prefixed with the attribute view name:
|
||||
* ```
|
||||
* [view_name:]attribute_name
|
||||
* ```
|
||||
* When the view name is not specified, it defaults to `basic`.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the attribute view is not supported.
|
||||
* @throws IllegalArgumentException if the attribute name is not specified or is not recognized, or
|
||||
* the attribute value is of the correct type but has an inappropriate value.
|
||||
* @throws ClassCastException if the attribute value is not of the expected type
|
||||
* @see Files.setAttribute
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.setAttribute(attribute: String, value: Any?, vararg options: LinkOption): Path =
|
||||
Files.setAttribute(this, attribute, value, *options)
|
||||
|
||||
/**
|
||||
* Returns a file attributes view of a given type [V]
|
||||
* or `null` if the requested attribute view type is not available.
|
||||
*
|
||||
* The returned view allows to read and optionally to modify attributes of a file.
|
||||
*
|
||||
* @param V the reified type of the desired attribute view.
|
||||
*
|
||||
* @see Files.getFileAttributeView
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <reified V : FileAttributeView> Path.fileAttributesViewOrNull(vararg options: LinkOption): V? =
|
||||
Files.getFileAttributeView(this, V::class.java, *options)
|
||||
|
||||
/**
|
||||
* Returns a file attributes view of a given type [V]
|
||||
* or throws an [UnsupportedOperationException] if the requested attribute view type is not available..
|
||||
*
|
||||
* The returned view allows to read and optionally to modify attributes of a file.
|
||||
*
|
||||
* @param V the reified type of the desired attribute view, a subtype of [FileAttributeView].
|
||||
*
|
||||
* @see Files.getFileAttributeView
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <reified V : FileAttributeView> Path.fileAttributesView(vararg options: LinkOption): V =
|
||||
Files.getFileAttributeView(this, V::class.java, *options) ?: fileAttributeViewNotAvailable(this, V::class.java)
|
||||
|
||||
@PublishedApi
|
||||
internal fun fileAttributeViewNotAvailable(path: Path, attributeViewClass: Class<*>): Nothing =
|
||||
throw UnsupportedOperationException("The desired attribute view type $attributeViewClass is not available for the file $path.")
|
||||
|
||||
/**
|
||||
* Reads a file's attributes of the specified type [A] in bulk.
|
||||
*
|
||||
* @param A the reified type of the desired attributes, a subtype of [BasicFileAttributes].
|
||||
*
|
||||
* @throws UnsupportedOperationException if the given attributes type [A] is not supported.
|
||||
* @see Files.readAttributes
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <reified A : BasicFileAttributes> Path.readAttributes(vararg options: LinkOption): A =
|
||||
Files.readAttributes(this, A::class.java, *options)
|
||||
|
||||
/**
|
||||
* Reads the specified list of attributes of a file in bulk.
|
||||
*
|
||||
* The list of [attributes] to read is specified in the following string form:
|
||||
* ```
|
||||
* [view:]attribute_name1[,attribute_name2...]
|
||||
* ```
|
||||
* So the names are comma-separated and optionally prefixed by the attribute view type name, `basic` by default.
|
||||
* The special `*` attribute name can be used to read all attributes of the specified view.
|
||||
*
|
||||
* @return a [Map<String, Any?>][Map] having an entry for an each attribute read, where the key is the attribute name and the value is the attribute value.
|
||||
* @throws UnsupportedOperationException if the attribute view is not supported.
|
||||
* @throws IllegalArgumentException if no attributes are specified or an unrecognized attribute is specified.
|
||||
* @see Files.readAttributes
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.readAttributes(attributes: String, vararg options: LinkOption): Map<String, Any?> =
|
||||
Files.readAttributes(this, attributes, *options)
|
||||
|
||||
/**
|
||||
* Returns the last modified time of the file located by this path.
|
||||
*
|
||||
* If the file system does not support modification timestamps, some implementation-specific default is returned.
|
||||
*
|
||||
* @see Files.getLastModifiedTime
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.getLastModifiedTime(vararg options: LinkOption): FileTime =
|
||||
Files.getLastModifiedTime(this, *options)
|
||||
|
||||
/**
|
||||
* Sets the last modified time attribute for the file located by this path.
|
||||
*
|
||||
* If the file system does not support modification timestamps, the behavior of this method is not defined.
|
||||
*
|
||||
* @see Files.setLastModifiedTime
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.setLastModifiedTime(value: FileTime): Path =
|
||||
Files.setLastModifiedTime(this, value)
|
||||
|
||||
/**
|
||||
* Returns the owner of a file.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the associated file system does not support the [FileOwnerAttributeView].
|
||||
*
|
||||
* @see Files.getOwner
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.getOwner(vararg options: LinkOption): UserPrincipal? =
|
||||
Files.getOwner(this, *options)
|
||||
|
||||
/**
|
||||
* Sets the file owner to the specified [value].
|
||||
*
|
||||
* @throws UnsupportedOperationException if the associated file system does not support the [FileOwnerAttributeView].
|
||||
*
|
||||
* @see Files.setOwner
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.setOwner(value: UserPrincipal): Path =
|
||||
Files.setOwner(this, value)
|
||||
|
||||
/**
|
||||
* Returns the POSIX file permissions of the file located by this path.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the associated file system does not support the [PosixFileAttributeView].
|
||||
*
|
||||
* @see Files.getPosixFilePermissions
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.getPosixFilePermissions(vararg options: LinkOption): Set<PosixFilePermission> =
|
||||
Files.getPosixFilePermissions(this, *options)
|
||||
|
||||
/**
|
||||
* Sets the POSIX file permissions for the file located by this path.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the associated file system does not support the [PosixFileAttributeView].
|
||||
*
|
||||
* @see Files.setPosixFilePermissions
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.setPosixFilePermissions(value: Set<PosixFilePermission>): Path =
|
||||
Files.setPosixFilePermissions(this, value)
|
||||
|
||||
/**
|
||||
* Creates a new link (directory entry) located by this path for the existing file [target].
|
||||
*
|
||||
* Calling this function may require the process to be started with implementation specific privileges to create hard links
|
||||
* or to create links to directories.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if a file with this name already exists
|
||||
* (optional specific exception, some implementations may throw a more general one).
|
||||
* @throws UnsupportedOperationException if the implementation does not support creating a hard link.
|
||||
*
|
||||
* @see Files.createLink
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.createLinkPointingTo(target: Path): Path =
|
||||
Files.createLink(this, target)
|
||||
|
||||
/**
|
||||
* Creates a new symbolic link located by this path to the given [target].
|
||||
*
|
||||
* Calling this function may require the process to be started with implementation specific privileges to
|
||||
* create symbolic links.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if a file with this name already exists
|
||||
* (optional specific exception, some implementations may throw a more general one).
|
||||
* @throws UnsupportedOperationException if the implementation does not support symbolic links or the
|
||||
* [attributes] array contains an attribute that cannot be set atomically when creating the symbolic link.
|
||||
*
|
||||
* @see Files.createSymbolicLink
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.createSymbolicLinkPointingTo(target: Path, vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createSymbolicLink(this, target, *attributes)
|
||||
|
||||
/**
|
||||
* Reads the target of a symbolic link located by this path.
|
||||
*
|
||||
* @throws UnsupportedOperationException if symbolic links are not supported by this implementation.
|
||||
* @throws NotLinkException if the target is not a symbolic link
|
||||
* (optional specific exception, some implementations may throw a more general one).
|
||||
*
|
||||
* @see Files.readSymbolicLink
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.readSymbolicLink(): Path =
|
||||
Files.readSymbolicLink(this)
|
||||
|
||||
/**
|
||||
* Creates a new and empty file specified by this path, failing if the file already exists.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the file.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if a file specified by this path already exists
|
||||
* (optional specific exception, some implementations may throw more general [IOException]).
|
||||
* @throws UnsupportedOperationException if the [attributes] array contains an attribute that cannot be set atomically
|
||||
* when creating the file.
|
||||
*
|
||||
* @see Files.createFile
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path.createFile(vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createFile(this, *attributes)
|
||||
|
||||
/**
|
||||
* Creates an empty file in the default temp directory, using
|
||||
* the given [prefix] and [suffix] to generate its name.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the file.
|
||||
* @return the path to the newly created file that did not exist before.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically
|
||||
* when creating the file.
|
||||
*
|
||||
* @see Files.createTempFile
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun createTempFile(prefix: String? = null, suffix: String? = null, vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createTempFile(prefix, suffix, *attributes)
|
||||
|
||||
/**
|
||||
* Creates an empty file in the specified [directory], using
|
||||
* the given [prefix] and [suffix] to generate its name.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the file.
|
||||
* @return the path to the newly created file that did not exist before.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically
|
||||
* when creating the file.
|
||||
*
|
||||
* @see Files.createTempFile
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun createTempFile(directory: Path, prefix: String? = null, suffix: String? = null, vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createTempFile(directory, prefix, suffix, *attributes)
|
||||
|
||||
/**
|
||||
* Creates a new directory in the default temp directory, using the given [prefix] to generate its name.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the directory.
|
||||
* @return the path to the newly created directory that did not exist before.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createTempDirectory
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun createTempDirectory(prefix: String? = null, vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createTempDirectory(prefix, *attributes)
|
||||
|
||||
/**
|
||||
* Creates a new directory in the specified [directory], using the given [prefix] to generate its name.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the directory.
|
||||
* @return the path to the newly created directory that did not exist before.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createTempDirectory
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun createTempDirectory(directory: Path, prefix: String? = null, vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createTempDirectory(directory, prefix, *attributes)
|
||||
|
||||
/**
|
||||
* Resolves the given [other] path against this path.
|
||||
*
|
||||
* This operator is a shortcut for the [Path.resolve] function.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun Path.div(other: Path): Path =
|
||||
this.resolve(other)
|
||||
|
||||
/**
|
||||
* Resolves the given [other] path string against this path.
|
||||
*
|
||||
* This operator is a shortcut for the [Path.resolve] function.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun Path.div(other: String): Path =
|
||||
this.resolve(other)
|
||||
|
||||
|
||||
/**
|
||||
* Converts the provided [path] string to a [Path] object of the [default][FileSystems.getDefault] filesystem.
|
||||
*
|
||||
* @see Paths.get
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path(path: String): Path =
|
||||
Paths.get(path)
|
||||
|
||||
/**
|
||||
* Converts the name sequence specified with the [base] path string and a number of [subpaths] additional names
|
||||
* to a [Path] object of the [default][FileSystems.getDefault] filesystem.
|
||||
*
|
||||
* @see Paths.get
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Path(base: String, vararg subpaths: String): Path =
|
||||
Paths.get(base, *subpaths)
|
||||
|
||||
/**
|
||||
* Converts this URI to a [Path] object.
|
||||
*
|
||||
* @see Paths.get
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
@ExperimentalPathApi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun URI.toPath(): Path =
|
||||
Paths.get(this)
|
||||
|
||||
@@ -7,38 +7,62 @@ package kotlin.jdk7.test
|
||||
|
||||
import java.io.IOException
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.*
|
||||
import kotlin.io.path.*
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.*
|
||||
|
||||
class PathExtensionsTest {
|
||||
private val isCaseInsensitiveFileSystem = Paths.get("C:/") == Paths.get("c:/")
|
||||
private val isCaseInsensitiveFileSystem = Path("C:/") == Path("c:/")
|
||||
private val isBackslashSeparator = FileSystems.getDefault().separator == "\\"
|
||||
|
||||
@Test
|
||||
fun extension() {
|
||||
assertEquals("bbb", Paths.get("aaa.bbb").extension)
|
||||
assertEquals("", Paths.get("aaa").extension)
|
||||
assertEquals("", Paths.get("aaa.").extension)
|
||||
assertEquals("bbb", Paths.get(".bbb").extension)
|
||||
assertEquals("", Paths.get("/my.dir/log").extension)
|
||||
assertEquals("", Paths.get("/").extension)
|
||||
fun filenameComponents() {
|
||||
fun check(path: String, name: String, nameNoExt: String, extension: String) {
|
||||
val p = Path(path)
|
||||
assertEquals(name, p.name, "name")
|
||||
assertEquals(nameNoExt, p.nameWithoutExtension, "nameWithoutExtension")
|
||||
assertEquals(extension, p.extension, "extension")
|
||||
}
|
||||
|
||||
check(path = "aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb")
|
||||
check(path = "aaa", name = "aaa", nameNoExt = "aaa", extension = "")
|
||||
check(path = "aaa.", name = "aaa.", nameNoExt = "aaa", extension = "")
|
||||
check(path = ".aaa", name = ".aaa", nameNoExt = "", extension = "aaa")
|
||||
check(path = "/dir.ext/aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb")
|
||||
check(path = "/dir.ext/aaa", name = "aaa", nameNoExt = "aaa", extension = "")
|
||||
check(path = "/", name = "", nameNoExt = "", extension = "")
|
||||
check(path = "", name = "", nameNoExt = "", extension = "")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nameWithoutExtension() {
|
||||
assertEquals("aaa", Paths.get("aaa.bbb").nameWithoutExtension)
|
||||
assertEquals("aaa", Paths.get("aaa").nameWithoutExtension)
|
||||
assertEquals("aaa", Paths.get("aaa.").nameWithoutExtension)
|
||||
assertEquals("", Paths.get(".bbb").nameWithoutExtension)
|
||||
assertEquals("log", Paths.get("/my.dir/log").nameWithoutExtension)
|
||||
assertEquals("", Paths.get("").nameWithoutExtension)
|
||||
assertEquals("", Paths.get("/").nameWithoutExtension)
|
||||
fun invariantSeparators() {
|
||||
val path = Path("base") / "nested" / "leaf"
|
||||
assertEquals("base/nested/leaf", path.invariantSeparatorsPath)
|
||||
|
||||
val path2 = Path("base", "nested", "leaf")
|
||||
assertEquals("base/nested/leaf", path2.invariantSeparatorsPath)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCopyTo() {
|
||||
val srcFile = Files.createTempFile(null, null)
|
||||
val dstFile = Files.createTempFile(null, null)
|
||||
fun createNewFile() {
|
||||
val dir = createTempDirectory()
|
||||
|
||||
val file = dir / "new-file"
|
||||
|
||||
assertTrue(file.notExists())
|
||||
|
||||
file.createFile()
|
||||
assertTrue(file.exists())
|
||||
assertTrue(file.isRegularFile())
|
||||
|
||||
assertFailsWith<FileAlreadyExistsException> { file.createFile() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun copyTo() {
|
||||
val srcFile = createTempFile()
|
||||
val dstFile = createTempFile()
|
||||
try {
|
||||
srcFile.writeText("Hello, World!")
|
||||
assertFailsWith<FileAlreadyExistsException>("copy do not overwrite existing file") {
|
||||
@@ -53,35 +77,34 @@ class PathExtensionsTest {
|
||||
srcFile.copyTo(srcFile, overwrite = true)
|
||||
compareFiles(dst, srcFile, "copying file to itself leaves it intact")
|
||||
|
||||
assertTrue(Files.deleteIfExists(dstFile))
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
dst = srcFile.copyTo(dstFile)
|
||||
compareFiles(srcFile, dst, "copy to new file")
|
||||
|
||||
val subDst = dstFile.resolve("foo/bar")
|
||||
assertFailsWith<NoSuchFileException> { srcFile.copyTo(subDst) }
|
||||
assertFailsWith<NoSuchFileException> { srcFile.copyTo(subDst, overwrite = true) }
|
||||
assertTrue(Files.deleteIfExists(dstFile))
|
||||
assertFailsWith<NoSuchFileException> { srcFile.copyTo(subDst) }
|
||||
assertFailsWith<FileSystemException> { srcFile.copyTo(subDst) }
|
||||
assertFailsWith<FileSystemException> { srcFile.copyTo(subDst, overwrite = true) }
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
assertFailsWith<FileSystemException> { srcFile.copyTo(subDst) }
|
||||
|
||||
Files.createDirectory(dstFile)
|
||||
val child = dstFile.resolve("child")
|
||||
Files.createFile(child)
|
||||
assertFailsWith<DirectoryNotEmptyException>( "copy with overwrite do not overwrite non-empty dir") {
|
||||
dstFile.createDirectory()
|
||||
val child = dstFile.resolve("child").createFile()
|
||||
assertFailsWith<DirectoryNotEmptyException>("copy with overwrite do not overwrite non-empty dir") {
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
}
|
||||
Files.delete(child)
|
||||
child.deleteExisting()
|
||||
|
||||
srcFile.copyTo(dstFile, overwrite = true)
|
||||
assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir")
|
||||
|
||||
assertTrue(Files.deleteIfExists(srcFile))
|
||||
assertTrue(Files.deleteIfExists(dstFile))
|
||||
assertTrue(srcFile.deleteIfExists())
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
|
||||
assertFailsWith<NoSuchFileException> {
|
||||
srcFile.copyTo(dstFile)
|
||||
}
|
||||
|
||||
Files.createDirectory(srcFile)
|
||||
srcFile.createDirectory()
|
||||
srcFile.resolve("somefile").writeText("some content")
|
||||
dstFile.writeText("")
|
||||
assertFailsWith<FileAlreadyExistsException>("copy dir do not overwrite file") {
|
||||
@@ -111,35 +134,141 @@ class PathExtensionsTest {
|
||||
|
||||
@Test
|
||||
fun copyToNameWithoutParent() {
|
||||
val currentDir = Paths.get("").toAbsolutePath()
|
||||
val srcFile = Files.createTempFile(null, null)
|
||||
val dstFile = Files.createTempFile(currentDir, null, null)
|
||||
val currentDir = Path("").toAbsolutePath()
|
||||
val srcFile = createTempFile()
|
||||
val dstFile = createTempFile(directory = currentDir)
|
||||
try {
|
||||
srcFile.writeText("Hello, World!", Charsets.UTF_8)
|
||||
Files.delete(dstFile)
|
||||
dstFile.deleteExisting()
|
||||
|
||||
val dstRelative = Paths.get(dstFile.fileName.toString())
|
||||
val dstRelative = Path(dstFile.name)
|
||||
|
||||
srcFile.copyTo(dstRelative)
|
||||
|
||||
assertEquals(srcFile.readText(), dstFile.readText())
|
||||
} finally {
|
||||
Files.delete(dstFile)
|
||||
Files.delete(srcFile)
|
||||
dstFile.deleteExisting()
|
||||
srcFile.deleteExisting()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun moveTo() {
|
||||
val original = createTempFile()
|
||||
val srcFile = createTempFile()
|
||||
val dstFile = createTempFile()
|
||||
fun restoreSrcFile() { original.copyTo(srcFile, overwrite = true) }
|
||||
try {
|
||||
original.writeText("Hello, World!")
|
||||
restoreSrcFile()
|
||||
|
||||
assertFailsWith<FileAlreadyExistsException>("do not overwrite existing file") {
|
||||
srcFile.moveTo(dstFile)
|
||||
}
|
||||
|
||||
var dst = srcFile.moveTo(dstFile, overwrite = true)
|
||||
assertSame(dst, dstFile)
|
||||
compareFiles(original, dst, "move with overwrite over existing file")
|
||||
assertTrue(srcFile.notExists())
|
||||
|
||||
restoreSrcFile()
|
||||
srcFile.moveTo(srcFile)
|
||||
srcFile.moveTo(srcFile, overwrite = true)
|
||||
|
||||
compareFiles(original, srcFile, "move file to itself leaves it intact")
|
||||
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
dst = srcFile.moveTo(dstFile)
|
||||
compareFiles(original, dst, "move to new file")
|
||||
|
||||
restoreSrcFile()
|
||||
val subDst = dstFile.resolve("foo/bar")
|
||||
assertFailsWith<FileSystemException> { srcFile.moveTo(subDst) }
|
||||
assertFailsWith<FileSystemException> { srcFile.moveTo(subDst, overwrite = true) }
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
assertFailsWith<FileSystemException> { srcFile.moveTo(subDst) }
|
||||
|
||||
dstFile.createDirectory()
|
||||
val child = dstFile.resolve("child").createFile()
|
||||
assertFailsWith<DirectoryNotEmptyException>("move with overwrite do not overwrite non-empty dir") {
|
||||
srcFile.moveTo(dstFile, overwrite = true)
|
||||
}
|
||||
child.deleteExisting()
|
||||
|
||||
srcFile.moveTo(dstFile, overwrite = true)
|
||||
compareFiles(original, dstFile, "move with overwrite over empty dir")
|
||||
|
||||
assertTrue(srcFile.notExists())
|
||||
assertTrue(dstFile.deleteIfExists())
|
||||
|
||||
assertFailsWith<NoSuchFileException> {
|
||||
srcFile.moveTo(dstFile)
|
||||
}
|
||||
|
||||
srcFile.createDirectory()
|
||||
srcFile.resolve("somefile").writeText("some content")
|
||||
dstFile.writeText("")
|
||||
assertFailsWith<FileAlreadyExistsException>("move dir do not overwrite file") {
|
||||
srcFile.moveTo(dstFile)
|
||||
}
|
||||
srcFile.moveTo(dstFile, overwrite = true)
|
||||
assertTrue(dstFile.isDirectory())
|
||||
assertEquals(listOf(dstFile / "somefile"), dstFile.listDirectoryEntries(), "directory is moved with its content")
|
||||
} finally {
|
||||
srcFile.toFile().deleteRecursively()
|
||||
dstFile.toFile().deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareFiles(src: Path, dst: Path, message: String? = null) {
|
||||
assertTrue(dst.exists())
|
||||
assertEquals(src.isRegularFile(), dst.isRegularFile(), message)
|
||||
assertEquals(src.isDirectory(), dst.isDirectory(), message)
|
||||
if (dst.isRegularFile()) {
|
||||
assertTrue(src.readBytes().contentEquals(dst.readBytes()), message)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAttributeGettersOnFile() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
fun fileSize() {
|
||||
val file = createTempFile()
|
||||
assertEquals(0, file.fileSize())
|
||||
|
||||
file.writeBytes(ByteArray(100))
|
||||
assertEquals(100, file.fileSize())
|
||||
|
||||
file.appendText("Hello", Charsets.US_ASCII)
|
||||
assertEquals(105, file.fileSize())
|
||||
|
||||
file.deleteExisting()
|
||||
assertFailsWith<NoSuchFileException> { file.fileSize() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deleteExisting() {
|
||||
val file = createTempFile()
|
||||
file.deleteExisting()
|
||||
assertFailsWith<NoSuchFileException> { file.deleteExisting() }
|
||||
|
||||
val dir = createTempDirectory()
|
||||
dir.deleteExisting()
|
||||
assertFailsWith<NoSuchFileException> { dir.deleteExisting() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deleteIfExists() {
|
||||
val file = createTempFile()
|
||||
assertTrue(file.deleteIfExists())
|
||||
assertFalse(file.deleteIfExists())
|
||||
|
||||
val dir = createTempDirectory()
|
||||
assertTrue(dir.deleteIfExists())
|
||||
assertFalse(dir.deleteIfExists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun attributeGettersOnFile() {
|
||||
val file = createTempFile("temp", ".file")
|
||||
assertTrue(file.exists())
|
||||
assertFalse(file.notExists())
|
||||
assertTrue(file.isRegularFile())
|
||||
@@ -147,17 +276,18 @@ class PathExtensionsTest {
|
||||
assertFalse(file.isSymbolicLink())
|
||||
assertTrue(file.isReadable())
|
||||
assertTrue(file.isWritable())
|
||||
assertTrue(file.isSameFile(file))
|
||||
assertTrue(file.isSameFileAs(file))
|
||||
|
||||
// The default value of these depends on the current operating system, so just check that
|
||||
// they don't throw an exception.
|
||||
file.isExecutable()
|
||||
file.isHidden()
|
||||
file.deleteExisting()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAttributeGettersOnDirectory() {
|
||||
val file = Files.createTempDirectory(null)
|
||||
fun attributeGettersOnDirectory() {
|
||||
val file = createTempDirectory(".tmpdir")
|
||||
assertTrue(file.exists())
|
||||
assertFalse(file.notExists())
|
||||
assertFalse(file.isRegularFile())
|
||||
@@ -165,15 +295,16 @@ class PathExtensionsTest {
|
||||
assertFalse(file.isSymbolicLink())
|
||||
assertTrue(file.isReadable())
|
||||
assertTrue(file.isWritable())
|
||||
assertTrue(file.isSameFile(file))
|
||||
assertTrue(file.isSameFileAs(file))
|
||||
|
||||
file.isExecutable()
|
||||
file.isHidden()
|
||||
file.deleteExisting()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAttributeGettersOnNonExistentPath() {
|
||||
val file = Files.createTempDirectory(null).resolve("foo")
|
||||
fun attributeGettersOnNonExistentPath() {
|
||||
val file = createTempDirectory().resolve("foo")
|
||||
assertFalse(file.exists())
|
||||
assertTrue(file.notExists())
|
||||
assertFalse(file.isRegularFile())
|
||||
@@ -181,7 +312,7 @@ class PathExtensionsTest {
|
||||
assertFalse(file.isSymbolicLink())
|
||||
assertFalse(file.isReadable())
|
||||
assertFalse(file.isWritable())
|
||||
assertTrue(file.isSameFile(file))
|
||||
assertTrue(file.isSameFileAs(file))
|
||||
|
||||
file.isExecutable()
|
||||
// This function will either throw an exception or return false,
|
||||
@@ -190,15 +321,95 @@ class PathExtensionsTest {
|
||||
assertFalse(file.isHidden())
|
||||
} catch (e: IOException) {
|
||||
}
|
||||
file.parent.deleteExisting()
|
||||
}
|
||||
|
||||
private interface SpecialFileAttributesView : FileAttributeView
|
||||
private interface SpecialFileAttributes : BasicFileAttributes
|
||||
|
||||
@Test
|
||||
fun readWriteAttributes() {
|
||||
val file = createTempFile()
|
||||
val modifiedTime = file.getLastModifiedTime()
|
||||
assertEquals(modifiedTime, file.getAttribute("lastModifiedTime"))
|
||||
assertEquals(modifiedTime, file.getAttribute("basic:lastModifiedTime"))
|
||||
assertEquals(modifiedTime, file.readAttributes<BasicFileAttributes>().lastModifiedTime())
|
||||
assertEquals(modifiedTime, file.readAttributes("basic:lastModifiedTime,creationTime")["lastModifiedTime"])
|
||||
assertEquals(modifiedTime, file.readAttributes("*")["lastModifiedTime"])
|
||||
|
||||
assertFailsWith<UnsupportedOperationException> { file.readAttributes<SpecialFileAttributes>() }
|
||||
assertFailsWith<UnsupportedOperationException> { file.readAttributes("really_unsupported_view:*") }
|
||||
assertFailsWith<IllegalArgumentException> { file.readAttributes("basic:really_unknown_attribute") }
|
||||
|
||||
val newTime1 = FileTime.fromMillis(modifiedTime.toMillis() + 3600_000)
|
||||
file.setLastModifiedTime(newTime1)
|
||||
assertEquals(newTime1, file.getLastModifiedTime())
|
||||
|
||||
val newTime2 = FileTime.fromMillis(modifiedTime.toMillis() + 2 * 3600_000)
|
||||
file.setAttribute("lastModifiedTime", newTime2)
|
||||
assertEquals(newTime2, file.getLastModifiedTime())
|
||||
|
||||
val newTime3 = FileTime.fromMillis(modifiedTime.toMillis() + 3 * 3600_000)
|
||||
file.fileAttributesView<BasicFileAttributeView>().setTimes(newTime3, null, null)
|
||||
assertEquals(newTime3, file.getLastModifiedTime())
|
||||
|
||||
assertFailsWith<UnsupportedOperationException> { file.fileAttributesView<SpecialFileAttributesView>() }
|
||||
assertNull(file.fileAttributesViewOrNull<SpecialFileAttributesView>())
|
||||
|
||||
file.setAttribute("lastModifiedTime", null)
|
||||
assertEquals(newTime3, file.getLastModifiedTime())
|
||||
|
||||
file.deleteExisting()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListDirectoryEntries() {
|
||||
val dir = Files.createTempDirectory(null)
|
||||
fun links() {
|
||||
val dir = createTempDirectory()
|
||||
val original = createTempFile(dir)
|
||||
original.writeBytes(Random.nextBytes(100))
|
||||
|
||||
val link = try {
|
||||
(dir / ("link-" + original.fileName)).createLinkPointingTo(original)
|
||||
} catch (e: IOException) {
|
||||
// may require a privilege
|
||||
println("Creating a link failed with ${e.stackTraceToString()}")
|
||||
return
|
||||
}
|
||||
|
||||
assertTrue(link.isRegularFile())
|
||||
assertTrue(link.isRegularFile(LinkOption.NOFOLLOW_LINKS))
|
||||
assertTrue(original.isSameFileAs(link))
|
||||
compareFiles(original, link)
|
||||
assertFailsWith<NotLinkException> { link.readSymbolicLink() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun symlinks() {
|
||||
val dir = createTempDirectory()
|
||||
val original = createTempFile(dir)
|
||||
original.writeBytes(Random.nextBytes(100))
|
||||
|
||||
val symlink = try {
|
||||
(dir / ("symlink-" + original.fileName)).createSymbolicLinkPointingTo(original)
|
||||
} catch (e: IOException) {
|
||||
// may require a privilege
|
||||
println("Creating a symlink failed with ${e.stackTraceToString()}")
|
||||
return
|
||||
}
|
||||
|
||||
assertTrue(symlink.isRegularFile())
|
||||
assertFalse(symlink.isRegularFile(LinkOption.NOFOLLOW_LINKS))
|
||||
assertTrue(original.isSameFileAs(symlink))
|
||||
compareFiles(original, symlink)
|
||||
assertEquals(original, symlink.readSymbolicLink())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun directoryEntriesList() {
|
||||
val dir = createTempDirectory()
|
||||
assertEquals(0, dir.listDirectoryEntries().size)
|
||||
|
||||
val file = dir.resolve("f1")
|
||||
Files.createFile(file)
|
||||
val file = dir.resolve("f1").createFile()
|
||||
assertEquals(listOf(file), dir.listDirectoryEntries())
|
||||
|
||||
val fileTxt = createTempFile(dir, suffix = ".txt")
|
||||
@@ -208,12 +419,11 @@ class PathExtensionsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUseDirectoryEntries() {
|
||||
val dir = Files.createTempDirectory(null)
|
||||
fun directoryEntriesUseSequence() {
|
||||
val dir = createTempDirectory()
|
||||
assertEquals(0, dir.useDirectoryEntries { it.toList() }.size)
|
||||
|
||||
val file = dir.resolve("f1")
|
||||
Files.createFile(file)
|
||||
val file = dir.resolve("f1").createFile()
|
||||
assertEquals(listOf(file), dir.useDirectoryEntries { it.toList() })
|
||||
|
||||
val fileTxt = createTempFile(dir, suffix = ".txt")
|
||||
@@ -223,12 +433,11 @@ class PathExtensionsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testForEachDirectoryEntry() {
|
||||
val dir = Files.createTempDirectory(null)
|
||||
fun directoryEntriesForEach() {
|
||||
val dir = createTempDirectory()
|
||||
dir.forEachDirectoryEntry { error("shouldn't get here, but received $it") }
|
||||
|
||||
val file = dir.resolve("f1")
|
||||
Files.createFile(file)
|
||||
val file = createTempFile(dir)
|
||||
dir.forEachDirectoryEntry { assertEquals(file, it) }
|
||||
|
||||
val fileTxt = createTempFile(dir, suffix = ".txt")
|
||||
@@ -239,9 +448,9 @@ class PathExtensionsTest {
|
||||
|
||||
|
||||
private fun testRelativeTo(expected: String?, path: String, base: String) =
|
||||
testRelativeTo(expected?.let { Paths.get(it) }, Paths.get(path), Paths.get(base))
|
||||
testRelativeTo(expected?.let { Path(it) }, Path(path), Path(base))
|
||||
private fun testRelativeTo(expected: String, path: Path, base: Path) =
|
||||
testRelativeTo(Paths.get(expected), path, base)
|
||||
testRelativeTo(Path(expected), path, base)
|
||||
|
||||
private fun testRelativeTo(expected: Path?, path: Path, base: Path) {
|
||||
val context = "path: '$path', base: '$base'"
|
||||
@@ -304,23 +513,23 @@ class PathExtensionsTest {
|
||||
|
||||
@Test
|
||||
fun relativeToRelative() {
|
||||
val nested = Paths.get("foo/bar")
|
||||
val base = Paths.get("foo")
|
||||
val nested = Path("foo/bar")
|
||||
val base = Path("foo")
|
||||
|
||||
testRelativeTo("bar", nested, base)
|
||||
testRelativeTo("..", base, nested)
|
||||
|
||||
val empty = Paths.get("")
|
||||
val current = Paths.get(".")
|
||||
val parent = Paths.get("..")
|
||||
val outOfRoot = Paths.get("../bar")
|
||||
val empty = Path("")
|
||||
val current = Path(".")
|
||||
val parent = Path("..")
|
||||
val outOfRoot = Path("../bar")
|
||||
|
||||
testRelativeTo("../bar", outOfRoot, empty)
|
||||
testRelativeTo("../../bar", outOfRoot, base)
|
||||
testRelativeTo("bar", outOfRoot, parent)
|
||||
testRelativeTo("..", parent, outOfRoot)
|
||||
|
||||
val root = Paths.get("/root")
|
||||
val root = Path("/root")
|
||||
val files = listOf(nested, base, empty, outOfRoot, current, parent)
|
||||
val bases = listOf(nested, base, empty, current)
|
||||
|
||||
@@ -340,10 +549,10 @@ class PathExtensionsTest {
|
||||
|
||||
@Test
|
||||
fun relativeToFails() {
|
||||
val absolute = Paths.get("/foo/bar/baz")
|
||||
val relative = Paths.get("foo/bar")
|
||||
val networkShare1 = Paths.get("""\\my.host\share1/folder""")
|
||||
val networkShare2 = Paths.get("""\\my.host\share2\folder""")
|
||||
val absolute = Path("/foo/bar/baz")
|
||||
val relative = Path("foo/bar")
|
||||
val networkShare1 = Path("""\\my.host\share1/folder""")
|
||||
val networkShare2 = Path("""\\my.host\share2\folder""")
|
||||
|
||||
val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList()
|
||||
for (file in allFiles) {
|
||||
|
||||
@@ -8,24 +8,25 @@ package kotlin.jdk7.test
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardOpenOption
|
||||
import kotlin.io.path.*
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.*
|
||||
|
||||
class PathReadWriteTest {
|
||||
@Test
|
||||
fun testAppendText() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
fun appendText() {
|
||||
val file = createTempFile()
|
||||
file.writeText("Hello\n")
|
||||
file.appendText("World\n")
|
||||
file.writeText("Again", Charsets.US_ASCII, StandardOpenOption.APPEND)
|
||||
|
||||
assertEquals("Hello\nWorld\nAgain", file.readText())
|
||||
assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8))
|
||||
file.toFile().deleteOnExit()
|
||||
file.deleteExisting()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun file() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
val file = createTempFile()
|
||||
val writer = file.outputStream().writer().buffered()
|
||||
|
||||
writer.write("Hello")
|
||||
@@ -72,31 +73,54 @@ class PathReadWriteTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBufferedReader() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
fun bufferedReader() {
|
||||
val file = createTempFile()
|
||||
val lines = listOf("line1", "line2")
|
||||
Files.write(file, lines, Charsets.UTF_8)
|
||||
file.writeLines(lines)
|
||||
|
||||
assertEquals(file.bufferedReader().use { it.readLines() }, lines)
|
||||
assertEquals(file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }, lines)
|
||||
assertEquals(lines, file.bufferedReader().use { it.readLines() })
|
||||
assertEquals(lines, file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBufferedWriter() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
fun bufferedWriter() {
|
||||
val file = createTempFile()
|
||||
|
||||
file.bufferedWriter().use { it.write("line1\n") }
|
||||
file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line2\n") }
|
||||
|
||||
assertEquals(Files.readAllLines(file, Charsets.UTF_8), listOf("line1", "line2"))
|
||||
assertEquals(listOf("line1", "line2"), file.readLines())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteBytes() {
|
||||
val file = Files.createTempFile(null, null)
|
||||
fun writeBytes() {
|
||||
val file = createTempFile()
|
||||
file.writeBytes("Hello".encodeToByteArray())
|
||||
file.appendBytes(" world!".encodeToByteArray())
|
||||
assertEquals(file.readText(), "Hello world!")
|
||||
|
||||
val bytes = Random.nextBytes(100)
|
||||
file.writeBytes(bytes)
|
||||
file.appendBytes(bytes)
|
||||
assertTrue((bytes + bytes) contentEquals file.readBytes())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeLines() {
|
||||
val file = createTempFile()
|
||||
val lines = listOf("first line", "second line")
|
||||
file.writeLines(lines)
|
||||
assertEquals(lines, file.readLines())
|
||||
|
||||
file.writeLines(lines.asSequence())
|
||||
assertEquals(lines, file.readLines())
|
||||
|
||||
val moreLines = listOf("third line", "the bottom line")
|
||||
file.appendLines(moreLines)
|
||||
assertEquals(lines + moreLines, file.readLines())
|
||||
|
||||
file.appendLines(moreLines.asSequence())
|
||||
assertEquals(lines + moreLines + moreLines, file.readLines())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -1,3 +1,23 @@
|
||||
public abstract interface annotation class kotlin/io/path/ExperimentalPathApi : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public final class kotlin/io/path/PathsKt {
|
||||
public static final fun appendText (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;)V
|
||||
public static synthetic fun appendText$default (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;ILjava/lang/Object;)V
|
||||
public static final fun fileAttributeViewNotAvailable (Ljava/nio/file/Path;Ljava/lang/Class;)Ljava/lang/Void;
|
||||
public static final fun getExtension (Ljava/nio/file/Path;)Ljava/lang/String;
|
||||
public static final fun getInvariantSeparatorsPath (Ljava/nio/file/Path;)Ljava/lang/String;
|
||||
public static final fun getName (Ljava/nio/file/Path;)Ljava/lang/String;
|
||||
public static final fun getNameWithoutExtension (Ljava/nio/file/Path;)Ljava/lang/String;
|
||||
public static final fun listDirectoryEntries (Ljava/nio/file/Path;Ljava/lang/String;)Ljava/util/List;
|
||||
public static synthetic fun listDirectoryEntries$default (Ljava/nio/file/Path;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List;
|
||||
public static final fun relativeTo (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path;
|
||||
public static final fun relativeToOrNull (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path;
|
||||
public static final fun relativeToOrSelf (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path;
|
||||
public static final fun writeText (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;[Ljava/nio/file/OpenOption;)V
|
||||
public static synthetic fun writeText$default (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;[Ljava/nio/file/OpenOption;ILjava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class kotlin/jdk7/AutoCloseableKt {
|
||||
public static final fun closeFinally (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user