https://kotlinlang.org logo
#getting-started
Title
# getting-started
n

nilTheDev

08/19/2021, 4:49 PM
Something is wrong with my code that works with File IO.
Copy code
fun main() {
    val strs = listOf(
        "line1",
        "line2"
    )
    val writer = File("src/main/resources/logging/temp.txt")
        .writer()

    strs.forEach { writer.appendLine(it) }
    writer.close()
}
The
temp.txt
file is empty when I run this program. After that the contents of the
temp.txt
file looks something like this,
Copy code
line1
line2
This is a perfectly reasonable output. However, things go wrong when I run a slightly modified version of the code for the second time.
Copy code
fun main() {
    val strs = listOf(
        "line3",
        "line4"
    )
    val writer = File("src/main/resources/logging/temp.txt")
        .writer()

    strs.forEach { writer.appendLine(it) }
    writer.close()
}
This is the new version. But this time the
temp.txt
file wasn't empty. It had the output of the first program saved into it. However, after running the new version the
temp.txt
file looks like this,
Copy code
line3
line4
The contents written by the first program are completely wiped out. Isn't the
temp.txt
file supposed to look like this?
Copy code
line1
line2
line3
line4
If not then what's even the point of using
append
over
write
? Isn't
append
expected to write new content after the previously added content instead of wiping out and starting afresh? Or, am I missing something?
k

Klitos Kyriacou

08/19/2021, 5:01 PM
What is happening is that you're calling the
writer()
extension to
java.io.File
. This extension creates a new
java.io.FileWriter
which it constructs without the
append
argument, so that this FileWriter truncates the file. The
append
method you're calling comes from the FileWriter's
Appendable
interface - nothing to do with appending to the file.
n

nilTheDev

08/19/2021, 5:05 PM
@Klitos Kyriacou I see. But what is a proper way of appending to a text file?
p

Paul Griffith

08/19/2021, 5:05 PM
One of many options is to create your writer with
StandardOpenOption.APPEND
as an `OpenOption`:
Copy code
val writer = Path("C:/Users/pgriffith/Downloads/test.txt")
    .writer(options = arrayOf(StandardOpenOption.APPEND))
n

nilTheDev

08/19/2021, 5:07 PM
@Paul Griffith That seems a reasonable way to do that. But it feels kind of java-ish. Is there any idiomatic way to do it in Kotlin?
t

Tomasz Krakowiak

08/19/2021, 5:18 PM
Well... Isn't Kotlin java-ish itself? ^^
😅 1
e

ephemient

08/19/2021, 5:20 PM
these IO extensions are Java-only to begin with…
p

Paul Griffith

08/19/2021, 5:20 PM
Kotlin doesn't have multiplatform file IO (yet), so you're going to be calling a Java API to read a file no matter what. The
writer
extension is already significantly nicer than the
Files
static method you'd use in plain Java
e

ephemient

08/19/2021, 5:21 PM
you can define your own with an
append: Boolean
parameter
also, you should probably use
.use { }
(equivalent to try-with-resources in Java) to auto-close at the end of the block, and consider using
.buffered
p

Paul Griffith

08/19/2021, 5:23 PM
Heh, actually, if you use Path you've actually already got an even nicer API -
path.appendLines()
Copy code
public inline fun Path.appendLines(lines: Iterable<CharSequence>, charset: Charset = Charsets.UTF_8): Path {
for more explicit use of a buffered writer if this is going to end up a large file/you're writing many lines, though