[scala] Scala: write string to file in one statement

For reading files in Scala, there is

Source.fromFile("file.txt").mkString

Is there an equivalent and concise way to write a string to file?

Most languages support something like that. My favorite is Groovy:

def f = new File("file.txt")
// Read
def s = f.text
// Write
f.text = "file contents"

I'd like to use the code for programs ranging from a single line to a short page of code. Having to use your own library doesn't make sense here. I expect a modern language to let me write something to a file conveniently.

There are posts similar to this, but they don't answer my exact question or are focused on older Scala versions.

For example:

This question is related to scala scala-2.9

The answer is


It is strange that no one had suggested NIO.2 operations (available since Java 7):

import java.nio.file.{Paths, Files}
import java.nio.charset.StandardCharsets

Files.write(Paths.get("file.txt"), "file contents".getBytes(StandardCharsets.UTF_8))

I think this is by far the simplest and easiest and most idiomatic way, and it does not need any dependencies sans Java itself.


A micro library I wrote: https://github.com/pathikrit/better-files

file.write("Hi!")

or

file << "Hi!"

Here is a concise one-liner using reflect.io.file, this works with Scala 2.12:

reflect.io.File("filename").writeAll("hello world")

Alternatively, if you want to use the Java libraries you can do this hack:

Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}

One also has this format, which is both concise and the underlying library is beautifully written (see the source code):

import scalax.io.Codec
import scalax.io.JavaConverters._

implicit val codec = Codec.UTF8

new java.io.File("hi-file.txt").asOutput.write("I'm a hi file! ... Really!")

If you like Groovy syntax, you can use the Pimp-My-Library design pattern to bring it to Scala:

import java.io._
import scala.io._

class RichFile( file: File ) {

  def text = Source.fromFile( file )(Codec.UTF8).mkString

  def text_=( s: String ) {
    val out = new PrintWriter( file , "UTF-8")
    try{ out.print( s ) }
    finally{ out.close }
  }
}

object RichFile {

  implicit def enrichFile( file: File ) = new RichFile( file )

}

It will work as expected:

scala> import RichFile.enrichFile
import RichFile.enrichFile

scala> val f = new File("/tmp/example.txt")
f: java.io.File = /tmp/example.txt

scala> f.text = "hello world"

scala> f.text
res1: String = 
"hello world

I know it's not one line, but it solves the safety issues as far as I can tell;

// This possibly creates a FileWriter, but maybe not
val writer = Try(new FileWriter(new File("filename")))
// If it did, we use it to write the data and return it again
// If it didn't we skip the map and print the exception and return the original, just in-case it was actually .write() that failed
// Then we close the file
writer.map(w => {w.write("data"); w}).recoverWith{case e => {e.printStackTrace(); writer}}.map(_.close)

If you didn't care about the exception handling then you can write

writer.map(w => {w.writer("data"); w}).recoverWith{case _ => writer}.map(_.close)

import sys.process._
"echo hello world" #> new java.io.File("/tmp/example.txt") !

This is concise enough, I guess:

scala> import java.io._
import java.io._

scala> val w = new BufferedWriter(new FileWriter("output.txt"))
w: java.io.BufferedWriter = java.io.BufferedWriter@44ba4f

scala> w.write("Alice\r\nBob\r\nCharlie\r\n")

scala> w.close()

Use ammonite ops library. The syntax is very minimal, but the breadth of the library is almost as wide as what one would expect from attempting such a task in a shell scripting language like bash.

On the page I linked to, it shows numerous operations one can do with the library, but to answer this question, this is an example of writing to a file

import ammonite.ops._
write(pwd/'"file.txt", "file contents")

os-lib is the best modern way to write to a file, as mentioned here.

Here's how to write "hello" to the file.txt file.

os.write(os.pwd/"file.txt", "hello")

os-lib hides the Java ugliness and complexity (it uses the Java libs under the hood, so it's just as performant). See here for more info about using the lib.


You can do this with a mix of Java and Scala libraries. You will have full control over the character encoding. But unfortunately, the file handles will not be closed properly.

scala> import java.io.ByteArrayInputStream
import java.io.ByteArrayInputStream

scala> import java.io.FileOutputStream
import java.io.FileOutputStream

scala> BasicIO.transferFully(new ByteArrayInputStream("test".getBytes("UTF-8")), new FileOutputStream("test.txt"))

You can easily use Apache File Utils. Look at function writeStringToFile. We use this library in our projects.


UPDATE: I have since created a more effective solution upon which I have elaborated here: https://stackoverflow.com/a/34277491/501113

I find myself working more and more in the Scala Worksheet within the Scala IDE for Eclipse (and I believe there is something equivalent in IntelliJ IDEA). Anyway, I need to be able to do a one-liner to output some of the contents as I get the "Output exceeds cutoff limit." message if I am doing anything significant, especially with the Scala collections.

I came up with a one-liner I insert into the top of each new Scala Worksheet to simplify this (and so I don't have to do the whole external library import exercise for a very simple need). If you are a stickler and notice that it is technically two lines, it's only to make it more readable in this forum. It is a single line in my Scala Worksheet.

def printToFile(content: String, location: String = "C:/Users/jtdoe/Desktop/WorkSheet.txt") =
  Some(new java.io.PrintWriter(location)).foreach{f => try{f.write(content)}finally{f.close}}

And the usage is simply:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n")

This allows me to optionally provide the file name should I want to have additional files beyond the default (which completely overwrites the file each time the method is called).

So, the second usage is simply:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n", "C:/Users/jtdoe/Desktop/WorkSheet.txt")

Enjoy!


Through the magic of the semicolon, you can make anything you like a one-liner.

import java.io.PrintWriter
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.charset.StandardCharsets
import java.nio.file.StandardOpenOption
val outfile = java.io.File.createTempFile("", "").getPath
val outstream = new PrintWriter(Files.newBufferedWriter(Paths.get(outfile)
  , StandardCharsets.UTF_8
  , StandardOpenOption.WRITE)); outstream.println("content"); outstream.flush(); outstream.close()

Here's the modern, safe one liner:

java.nio.file.Files.write(java.nio.file.Paths.get("/tmp/output.txt"), "Hello world".getBytes());

nio is a modern IO library shipped by default with the JDK 9+ so no imports or dependencies required.