# Reading and writing text files

The easiest way to read a text file is the readText method of File: it simply returns the entire file as a single string:

>>> java.io.File("text.txt").readText()
When I started programming, there were no graphical displays.
All computer input and output was done using text.


If you want to read the lines into a List<String>, with one element for each line, you can use readLines():

>>> val fname = "words.txt"
>>> list.take(10)
[aa, aah, aahed, aahing, aahs, aal, aalii, aaliis, aals, aardvark]


If you want to store the lines in a set, or if you want to do some additional filtering or processing, the following is more efficient:

>>> val words = java.io.File(fname).useLines { it.toSet() }
>>> words.take(10)
[aa, aah, aahed, aahing, aahs, aal, aalii, aaliis, aals, aardvark]
>>> val some = java.io.File(fname).useLines { it.filter { it.length > 10}.map {it.toUpperCase() }.toList() }
>>> some.take(10)
[ABANDONMENT, ABANDONMENTS, ABBREVIATED, ABBREVIATES, ABBREVIATING,
ABBREVIATION, ABBREVIATIONS, ABDICATIONS, ABDOMINALLY,
ABERRATIONS]


If you need to do some more complicated processing on the lines of the file, the forEachLine method of the File class is convenient. It takes as argument a function object that takes one string argument. The method calls this function object for each line of the file in sequence:

>>> java.io.File(fname).forEachLine { print(it); print(' ') }
aa aah aahed aahing aahs aal aalii aaliis aals aardvark aardvarks
aardwolf aardwolves aas aasvogel aasvogels aba abaca abacas abaci
aback abacus abacuses abaft abaka abakas abalone abalones abamp
abampere abamperes abamps abandon abandoned ...


Note the use of the magic name it for the contents of each line.

If you need to do something more complicated, possibly resetting the reading to the beginning of the file, skipping parts of the file, etc., use a BufferedReader (readfile1.kts):

fun readFile(fname: String) {
while (line != null) {
println(line)
}
}


Note that readLine returns a String?, and you have to close the reader when you are done.

By wrapping the reading code in a use block, closing the reader becomes automatic (and happens even if we return early from the function or throw an exception) (readfile2.kts):

fun readFile(fname: String) {
while (line != null) {
println(line)
}
}
}


#### Writing text files

To write a text file, create a PrintWriter. It supports methods print and println, which works just like printing to the terminal. Don't forget to close the PrintWriter, otherwise your file will be incomplete: (writefile1.kts):

val out = java.io.File("test.txt").printWriter()

for (i in 1 .. 10)
out.println("$i:${i * i}")

out.close()


Again we can make closing the file automatic by using use: (writefile2.kts):

java.io.File("test.txt").printWriter().use {
out ->
for (i in 1 .. 10)
out.println("$i:${i * i}")
}