Revise functions in PathReadWrite

- Adjust implementations to avoid excessive vararg copies
- Remove options from forEachLine, it doesn't make much sense and
isn't consistent with the other read* functions.
- Revise inlineness of functions in PathReadWrite
- Compact implementations of those that are remained inline.
- Clarify docs of functions for reading the entire file

#KT-19192
This commit is contained in:
Ilya Gorbunov
2020-10-15 02:57:09 +03:00
parent a43cc0d1f9
commit fe098ec821
3 changed files with 34 additions and 20 deletions
@@ -26,7 +26,7 @@ import java.nio.file.StandardOpenOption
@ExperimentalPathApi @ExperimentalPathApi
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): InputStreamReader { public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): InputStreamReader {
return inputStream(*options).reader(charset) return InputStreamReader(Files.newInputStream(this, *options), charset)
} }
/** /**
@@ -44,7 +44,12 @@ public inline fun Path.bufferedReader(
bufferSize: Int = DEFAULT_BUFFER_SIZE, bufferSize: Int = DEFAULT_BUFFER_SIZE,
vararg options: OpenOption vararg options: OpenOption
): BufferedReader { ): BufferedReader {
return reader(charset, *options).buffered(bufferSize) return BufferedReader(
InputStreamReader(
Files.newInputStream(this, *options),
charset
),
bufferSize)
} }
/** /**
@@ -57,7 +62,7 @@ public inline fun Path.bufferedReader(
@ExperimentalPathApi @ExperimentalPathApi
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): OutputStreamWriter { public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): OutputStreamWriter {
return outputStream(*options).writer(charset) return OutputStreamWriter(Files.newOutputStream(this, *options), charset)
} }
/** /**
@@ -75,13 +80,19 @@ public inline fun Path.bufferedWriter(
bufferSize: Int = DEFAULT_BUFFER_SIZE, bufferSize: Int = DEFAULT_BUFFER_SIZE,
vararg options: OpenOption vararg options: OpenOption
): BufferedWriter { ): BufferedWriter {
return writer(charset, *options).buffered(bufferSize) return BufferedWriter(
OutputStreamWriter(
Files.newOutputStream(this, *options),
charset),
bufferSize)
} }
/** /**
* Gets the entire content of this file as a byte array. * Gets the entire content of this file as a byte array.
* *
* This method is not recommended on huge files. It has an internal limitation of 2 GB byte array size. * It's not recommended to use this function on huge files.
* It has an internal limitation of approximately 2 GB byte array size.
* For reading large files or files of unknown size, open an [InputStream][Path.inputStream] and read blocks sequentially.
* *
* @return the entire content of this file as a byte array. * @return the entire content of this file as a byte array.
*/ */
@@ -123,16 +134,16 @@ public inline fun Path.appendBytes(array: ByteArray) {
/** /**
* Gets the entire content of this file as a String using UTF-8 or the 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. * It's not recommended to use this function on huge files.
* For reading large files or files of unknown size, open a [Reader][Path.reader] and read blocks of text sequentially.
* *
* @param charset character set to use for reading text, UTF-8 by default. * @param charset character set to use for reading text, UTF-8 by default.
* @return the entire content of this file as a String. * @return the entire content of this file as a String.
*/ */
@SinceKotlin("1.4") @SinceKotlin("1.4")
@ExperimentalPathApi @ExperimentalPathApi
@kotlin.internal.InlineOnly public fun Path.readText(charset: Charset = Charsets.UTF_8): String =
public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String = reader(charset).use { it.readText() }
readBytes().toString(charset)
/** /**
* Sets the content of this file as [text] encoded using UTF-8 or the specified [charset]. * Sets the content of this file as [text] encoded using UTF-8 or the specified [charset].
@@ -146,8 +157,8 @@ public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String =
*/ */
@SinceKotlin("1.4") @SinceKotlin("1.4")
@ExperimentalPathApi @ExperimentalPathApi
public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Unit { public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption) {
writeBytes(text.toByteArray(charset), *options) Files.newOutputStream(this, *options).writer(charset).use { it.write(text) }
} }
/** /**
@@ -158,8 +169,8 @@ public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, varar
*/ */
@SinceKotlin("1.4") @SinceKotlin("1.4")
@ExperimentalPathApi @ExperimentalPathApi
public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit { public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8) {
writeText(text, charset, StandardOpenOption.APPEND) Files.newOutputStream(this, StandardOpenOption.APPEND).writer(charset).use { it.write(text) }
} }
/** /**
@@ -168,15 +179,15 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni
* *
* You may use this function on huge files. * You may use this function on huge files.
* *
* @param options options to determine how the file is opened.
* @param charset character set to use for reading text, UTF-8 by default. * @param charset character set to use for reading text, UTF-8 by default.
* @param action function to process file lines. * @param action function to process file lines.
*/ */
@SinceKotlin("1.4") @SinceKotlin("1.4")
@ExperimentalPathApi @ExperimentalPathApi
public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, vararg options: OpenOption, action: (line: String) -> Unit): Unit { @kotlin.internal.InlineOnly
// Note: close is called at forEachLine public inline fun Path.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit {
bufferedReader(charset, options = options).forEachLine(action) // cannot use non-inline forEachLine
Files.newBufferedReader(this, charset).useLines { it.forEach(action) }
} }
/** /**
@@ -210,7 +221,8 @@ public inline fun Path.outputStream(vararg options: OpenOption): OutputStream {
/** /**
* Reads the file content as a list of lines. * Reads the file content as a list of lines.
* *
* Do not use this function for huge files. * It's not recommended to use this function on huge files.
* For reading lines of a large file or a file of unknown size, use [Path.forEachLine] or [Path.useLines].
* *
* @param charset character set to use for reading text, UTF-8 by default. * @param charset character set to use for reading text, UTF-8 by default.
* @return list of file lines. * @return list of file lines.
@@ -233,7 +245,7 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List<String
@ExperimentalPathApi @ExperimentalPathApi
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <T> Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T { public inline fun <T> Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T {
return bufferedReader(charset).use { block(it.lineSequence()) } return Files.newBufferedReader(this, charset).use { block(it.lineSequence()) }
} }
/** /**
@@ -35,7 +35,7 @@ class PathReadWriteTest {
writer.close() writer.close()
val list = ArrayList<String>() val list = ArrayList<String>()
file.forEachLine(charset = Charsets.UTF_8, options = arrayOf(StandardOpenOption.READ)) { file.forEachLine(charset = Charsets.UTF_8) {
list.add(it) list.add(it)
} }
assertEquals(listOf("Hello", "World"), list) assertEquals(listOf("Hello", "World"), list)
@@ -11,6 +11,8 @@ public final class kotlin/io/path/PathsKt {
public static final fun getNameWithoutExtension (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 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 synthetic fun listDirectoryEntries$default (Ljava/nio/file/Path;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List;
public static final fun readText (Ljava/nio/file/Path;Ljava/nio/charset/Charset;)Ljava/lang/String;
public static synthetic fun readText$default (Ljava/nio/file/Path;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String;
public static final fun relativeTo (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; 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 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 relativeToOrSelf (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path;