For reading, there is the useful abstraction Source
. How can I write lines to a text file?

- 30,738
- 21
- 105
- 131

- 14,489
- 21
- 77
- 126
-
1If you know how to do so in Java then you can use the same in Scala. Is your question specifically with the Scala standard library? – wheaties Jan 05 '11 at 13:02
-
1@wheaties yes best way to do this in scala – yura Oct 10 '11 at 13:27
-
This library is really good: https://github.com/pathikrit/better-files – Robin Oct 12 '16 at 11:05
-
1Lihaoyi's OS-Lib library https://github.com/lihaoyi/os-lib – WeiChing 林煒清 Feb 01 '20 at 13:02
19 Answers
This is one of the features missing from standard Scala that I have found so useful that I add it to my personal library. (You probably should have a personal library, too.) The code goes like so:
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
val p = new java.io.PrintWriter(f)
try { op(p) } finally { p.close() }
}
and it's used like this:
import java.io._
val data = Array("Five","strings","in","a","file!")
printToFile(new File("example.txt")) { p =>
data.foreach(p.println)
}
-
1new java.io.PrintWriter() uses the platform default encoding, which probably means that the result file is not very portable. For example, if you want to produce a file that you can later send around by email, you should probably use the PrintWriter constructor that allows you to specify an encoding. – jcsahnwaldt Reinstate Monica Jul 15 '13 at 18:30
-
@JonaChristopherSahnwaldt - Sure, in special cases you might want to specify the encoding. The default for the platform is the most sensible default on average. Same as with `Source` (default encoding by default). You can of course add e.g. a `enc: Option[String] = None` parameter after `f` if you find this a common need. – Rex Kerr Jul 15 '13 at 20:01
-
6@RexKerr - I disagree. One should specify the encoding in almost all cases. Most encoding errors I encounter happen because people don't understand or don't think about encoding. They use the default and don't even know it because too many APIs let them get away with it. Nowadays, the most sensible default would probably be UTF-8. Maybe you only work with English and other languages that can be written in ASCII. Lucky you. I live in Germany and had to fix more broken umlauts than I care to remember. – jcsahnwaldt Reinstate Monica Jul 24 '13 at 17:01
-
3@JonaChristopherSahnwaldt - This is a reason to have a sensible default encoding, not to force everyone to specify it all the time. But if you're on a Mac and your files written by Java are gobbledygook because they aren't Mac OS Roman encoded, I'm not sure it's doing more good than harm. I think it's the platforms' fault that they haven't agreed on a charset. As an individual developer, typing in a string is really not going to solve the problem. (All developers agreeing on UTF-8 would, but then that can just go in as the default.) – Rex Kerr Jul 24 '13 at 17:14
-
@JonaChristopherSahnwaldt +10 for fixing all the broken umlaut. Can't use a hammer, maybe a hole punch? Or are they already holes that need filling, maybe this guy can help https://www.youtube.com/watch?v=E-eBBzWEpwE But seriously, the influence of ASCII is so damaging in the world, agree it should be specified, and default as UTF-8 – Davos Aug 08 '17 at 05:50
-
-
@JanacMeena - NIO just dumps bytes to a file with `Files.write` so you can just create a string, `getBytes` on it (probably asking for UTF-8 encoding), and pass that to `Files.write`. It's one-liner, albeit kind of a big one. – Rex Kerr Apr 01 '19 at 19:11
Edit 2019 (8 years later), Scala-IO being not very active, if any, Li Haoyi suggests his own library lihaoyi/os-lib
, that he presents below.
June 2019, Xavier Guihot mentions in his answer the library Using
, a utility for performing automatic resource management.
Edit (September 2011): since Eduardo Costa asks about Scala2.9, and since Rick-777 comments that scalax.IO commit history is pretty much non-existent since mid-2009...
Scala-IO has changed place: see its GitHub repo, from Jesse Eichar (also on SO):
The Scala IO umbrella project consists of a few sub projects for different aspects and extensions of IO.
There are two main components of Scala IO:
- Core - Core primarily deals with Reading and writing data to and from arbitrary sources and sinks. The corner stone traits are
Input
,Output
andSeekable
which provide the core API.
Other classes of importance areResource
,ReadChars
andWriteChars
.- File - File is a
File
(calledPath
) API that is based on a combination of Java 7 NIO filesystem and SBT PathFinder APIs.
Path
andFileSystem
are the main entry points into the Scala IO File API.
import scalax.io._
val output:Output = Resource.fromFile("someFile")
// Note: each write will open a new connection to file and
// each write is executed at the begining of the file,
// so in this case the last write will be the contents of the file.
// See Seekable for append and patching files
// Also See openOutput for performing several writes with a single connection
output.writeIntsAsBytes(1,2,3)
output.write("hello")(Codec.UTF8)
output.writeStrings(List("hello","world")," ")(Codec.UTF8)
Original answer (January 2011), with the old place for scala-io:
If you don't want to wait for Scala2.9, you can use the scala-incubator / scala-io library.
(as mentioned in "Why doesn't Scala Source close the underlying InputStream?")
See the samples
{ // several examples of writing data
import scalax.io.{
FileOps, Path, Codec, OpenOption}
// the codec must be defined either as a parameter of ops methods or as an implicit
implicit val codec = scalax.io.Codec.UTF8
val file: FileOps = Path ("file")
// write bytes
// By default the file write will replace
// an existing file with the new data
file.write (Array (1,2,3) map ( _.toByte))
// another option for write is openOptions which allows the caller
// to specify in detail how the write should take place
// the openOptions parameter takes a collections of OpenOptions objects
// which are filesystem specific in general but the standard options
// are defined in the OpenOption object
// in addition to the definition common collections are also defined
// WriteAppend for example is a List(Create, Append, Write)
file.write (List (1,2,3) map (_.toByte))
// write a string to the file
file.write("Hello my dear file")
// with all options (these are the default options explicitely declared)
file.write("Hello my dear file")(codec = Codec.UTF8)
// Convert several strings to the file
// same options apply as for write
file.writeStrings( "It costs" :: "one" :: "dollar" :: Nil)
// Now all options
file.writeStrings("It costs" :: "one" :: "dollar" :: Nil,
separator="||\n||")(codec = Codec.UTF8)
}

- 1,262,500
- 529
- 4,410
- 5,250
-
17
-
The scalax project seems dead (no commits since June 2009). Is this right? [scalax commit history](https://github.com/eengbrec/Scalax.IO/commits/master) – Rick-777 Sep 28 '11 at 20:24
-
@Eduardo: I have completed my answer with the new place for scala-io library (which has been updated for Scala2.9: https://github.com/jesseeichar/scala-io/issues/20) – VonC Sep 28 '11 at 20:54
-
@Rick-777: That is true. See my revised answer, with the new place for scala-io library. – VonC Sep 28 '11 at 20:55
-
10Is this really the current suggestion for Scala 2.10? Use Scala IO? There isn't anything in core Scala yet? – Phil Dec 23 '12 at 10:53
-
@Phil Scala 2.10 will have one version of Scala IO in it: http://daily-scala.blogspot.fr/2012/07/scala-io-getting-started.html – VonC Dec 23 '12 at 13:15
-
2I've never used scalax.io, but judging from these example lines, it seems that its API design is pretty bad. Mixing methods for character and binary data in one interface makes little sense and will very likely lead to encoding bugs that are hard to find. The design of java.io (Reader/Writer vs. InputStream/OutputStream) seems much better. – jcsahnwaldt Reinstate Monica Jul 15 '13 at 18:39
Similar to the answer by Rex Kerr, but more generic. First I use a helper function:
/**
* Used for reading/writing to database, files, etc.
* Code From the book "Beginning Scala"
* http://www.amazon.com/Beginning-Scala-David-Pollak/dp/1430219890
*/
def using[A <: {def close(): Unit}, B](param: A)(f: A => B): B =
try { f(param) } finally { param.close() }
Then I use this as:
def writeToFile(fileName:String, data:String) =
using (new FileWriter(fileName)) {
fileWriter => fileWriter.write(data)
}
and
def appendToFile(fileName:String, textData:String) =
using (new FileWriter(fileName, true)){
fileWriter => using (new PrintWriter(fileWriter)) {
printWriter => printWriter.println(textData)
}
}
etc.

- 17,824
- 28
- 99
- 157
-
40Don't get me wrong, I like your code and it is very educational, but the more I see such constructs for simple problems, the more it reminds me about old "hello world" joke: http://www.ariel.com.au/jokes/The_Evolution_of_a_Programmer.html :-) (+1 vote from me). – greenoldman Oct 09 '11 at 19:45
-
4If you're writing one-liners, nothing at all matters. If you're writing significant programs (large with an ongoing need for maintenance and evolution), this kind of thinking leads to the most rapid and pernicious kind of software quality degradation. – Randall Schulz Jan 01 '12 at 18:11
-
3Not everyone is going to have "scala eyes" until some level of practice -- it is funny to see this code example is coming from "Beginning" Scala – asyncwait Sep 03 '12 at 14:34
-
asyncwait "beginning" scala...the most ironic title ever,note: I've the book...and just now I'm beginning to understand it..I suppose than I was a step before "beginner" lol :D ........ – user1050817 Jul 19 '13 at 00:00
-
1The problem is less the Scala tricks here, but the verbosity and poor style. I've edited this to much more readable. After my refactor it's just 4 lines (well, 4 with IDE line lengths, used 6 here to fit in the screen). IMHO it is now very nice answer. – samthebest Nov 23 '13 at 11:08
-
@Jus12 : Don't forget to call fileWriter.close() def writeToFile(fileName:String, data:String) = using (new FileWriter(fileName)) { fileWriter => { fileWriter.write(data) fileWriter.close() } } ` – Sandro Athaide May 25 '14 at 23:11
-
@SandroAthaide `finally { param.close() }` takes care of closing. In fact, that is the only reason for using `using`. – Jus12 May 31 '14 at 07:18
-
Took me a while to understand this, but now that I do, it feels quite natural. Is `using` modeled after the python "`with` ... `as`"? – mitchus Jun 02 '14 at 13:18
-
@mitchus I'm guessing it's based on C#'s `using` statement. See samthebest's answer for a clearer, more idiomatic implementation. – GatesDA Jul 19 '14 at 16:23
A simple answer:
import java.io.File
import java.io.PrintWriter
def writeToFile(p: String, s: String): Unit = {
val pw = new PrintWriter(new File(p))
try pw.write(s) finally pw.close()
}

- 1,350
- 16
- 26

- 30,803
- 25
- 102
- 142
-
1
-
1As of java 7, use java.nio.file instead: def writeToFile(file: String, stringToWrite: String): Unit = { val writer = Files.newBufferedWriter(Paths.get(file)) try writer.write(stringToWrite) finally writer.close() } – E Shindler Sep 01 '16 at 13:33
Giving another answer, because my edits of other answers where rejected.
This is the most concise and simple answer (similar to Garret Hall's)
File("filename").writeAll("hello world")
This is similar to Jus12, but without the verbosity and with correct code style
def using[A <: {def close(): Unit}, B](resource: A)(f: A => B): B =
try f(resource) finally resource.close()
def writeToFile(path: String, data: String): Unit =
using(new FileWriter(path))(_.write(data))
def appendToFile(path: String, data: String): Unit =
using(new PrintWriter(new FileWriter(path, true)))(_.println(data))
Note you do NOT need the curly braces for try finally
, nor lambdas, and note usage of placeholder syntax. Also note better naming.

- 30,803
- 25
- 102
- 142
-
2Sorry, but your code is imaginable, it does not fulfill the `implemented` prerequisite. You cannot use the code that is not implemented. I mean that you must tell how to find it since it is not available by default and not well-known. – Val Mar 16 '15 at 14:10
Unfortunately for the top answer, Scala-IO is dead. If you don't mind using a third-party dependency, consider using my OS-Lib library. This makes working with files, paths and the filesystem very easy:
// Make sure working directory exists and is empty
val wd = os.pwd/"out"/"splash"
os.remove.all(wd)
os.makeDir.all(wd)
// Read/write files
os.write(wd/"file.txt", "hello")
os.read(wd/"file.txt") ==> "hello"
// Perform filesystem operations
os.copy(wd/"file.txt", wd/"copied.txt")
os.list(wd) ==> Seq(wd/"copied.txt", wd/"file.txt")
It has one-liners for writing to files, appending to files, overwriting files, and many other useful/common operations

- 15,330
- 17
- 80
- 137
Here is a concise one-liner using the Scala compiler library:
scala.tools.nsc.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}

- 54,987
- 21
- 291
- 190

- 29,524
- 10
- 61
- 76
-
-
-
3
-
1What are you talking about? `scala.tools.nsc.io.File("/tmp/myFile.txt")` works in Scala 2.11.8. – Jan 06 '17 at 12:35
-
1
One liners for saving/reading to/from String
, using java.nio
.
import java.nio.file.{Paths, Files, StandardOpenOption}
import java.nio.charset.{StandardCharsets}
import scala.collection.JavaConverters._
def write(filePath:String, contents:String) = {
Files.write(Paths.get(filePath), contents.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE)
}
def read(filePath:String):String = {
Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8).asScala.mkString
}
This isn't suitable for large files, but will do the job.
Some links:
java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString

- 14,952
- 7
- 53
- 50
-
-
2@ChetanBhasin Probably because `write` will copy `contents` to a new byte array instead of streaming it to the file, thereby at its peak using up twice as much memory than `contents` alone. – Daniel Werner Nov 03 '16 at 14:20
Starting Scala 2.13
, the standard library provides a dedicated resource management utility: Using
.
It can be used in this case with resources such as PrintWriter
or BufferedWriter
which extends AutoCloseable
in order to write to a file and, no matter what, close the resource afterwards:
For instance, with
java.io
api:import scala.util.Using, java.io.{PrintWriter, File} // val lines = List("hello", "world") Using(new PrintWriter(new File("file.txt"))) { writer => lines.foreach(writer.println) }
Or with
java.nio
api:import scala.util.Using, java.nio.file.{Files, Paths}, java.nio.charset.Charset // val lines = List("hello", "world") Using(Files.newBufferedWriter(Paths.get("file.txt"), Charset.forName("UTF-8"))) { writer => lines.foreach(line => writer.write(line + "\n")) }

- 54,987
- 21
- 291
- 190
A micro library I wrote: https://github.com/pathikrit/better-files
file.appendLine("Hello", "World")
or
file << "Hello" << "\n" << "World"

- 32,469
- 37
- 142
- 221
-
Here as well - This question is one of the top hits when googling how to write a file with scala -- now that your project has gotten bigger, you might want to expand your answer a bit? – asachet Jun 06 '17 at 16:55
UPDATE on 2019/Sep/01:
- Starting with Scala 2.13, prefer using scala.util.Using
- Fixed bug where
finally
would swallow originalException
thrown bytry
iffinally
code threw anException
After reviewing all of these answers on how to easily write a file in Scala, and some of them are quite nice, I had three issues:
- In the Jus12's answer, the use of currying for the using helper method is non-obvious for Scala/FP beginners
- Needs to encapsulate lower level errors with
scala.util.Try
- Needs to show Java developers new to Scala/FP how to properly nest dependent resources so the
close
method is performed on each dependent resource in reverse order - Note: closing dependent resources in reverse order ESPECIALLY IN THE EVENT OF A FAILURE is a rarely understood requirement of thejava.lang.AutoCloseable
specification which tends to lead to very pernicious and difficult to find bugs and run time failures
Before starting, my goal isn't conciseness. It's to facilitate easier understanding for Scala/FP beginners, typically those coming from Java. At the very end, I will pull all the bits together, and then increase the conciseness.
First, the using
method needs to be updated to use Try
(again, conciseness is not the goal here). It will be renamed to tryUsingAutoCloseable
:
def tryUsingAutoCloseable[A <: AutoCloseable, R]
(instantiateAutoCloseable: () => A) //parameter list 1
(transfer: A => scala.util.Try[R]) //parameter list 2
: scala.util.Try[R] =
Try(instantiateAutoCloseable())
.flatMap(
autoCloseable => {
var optionExceptionTry: Option[Exception] = None
try
transfer(autoCloseable)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
autoCloseable.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
The beginning of the above tryUsingAutoCloseable
method might be confusing because it appears to have two parameter lists instead of the customary single parameter list. This is called currying. And I won't go into detail how currying works or where it is occasionally useful. It turns out that for this particular problem space, it's the right tool for the job.
Next, we need to create method, tryPrintToFile
, which will create a (or overwrite an existing) File
and write a List[String]
. It uses a FileWriter
which is encapsulated by a BufferedWriter
which is in turn encapsulated by a PrintWriter
. And to elevate performance, a default buffer size much larger than the default for BufferedWriter
is defined, defaultBufferSize
, and assigned the value 65536.
Here's the code (and again, conciseness is not the goal here):
val defaultBufferSize: Int = 65536
def tryPrintToFile(
lines: List[String],
location: java.io.File,
bufferSize: Int = defaultBufferSize
): scala.util.Try[Unit] = {
tryUsingAutoCloseable(() => new java.io.FileWriter(location)) { //this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
fileWriter =>
tryUsingAutoCloseable(() => new java.io.BufferedWriter(fileWriter, bufferSize)) { //this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
bufferedWriter =>
tryUsingAutoCloseable(() => new java.io.PrintWriter(bufferedWriter)) { //this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
printWriter =>
scala.util.Try(
lines.foreach(line => printWriter.println(line))
)
}
}
}
}
The above tryPrintToFile
method is useful in that it takes a List[String]
as input and sends it to a File
. Let's now create a tryWriteToFile
method which takes a String
and writes it to a File
.
Here's the code (and I'll let you guess conciseness's priority here):
def tryWriteToFile(
content: String,
location: java.io.File,
bufferSize: Int = defaultBufferSize
): scala.util.Try[Unit] = {
tryUsingAutoCloseable(() => new java.io.FileWriter(location)) { //this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
fileWriter =>
tryUsingAutoCloseable(() => new java.io.BufferedWriter(fileWriter, bufferSize)) { //this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
bufferedWriter =>
Try(bufferedWriter.write(content))
}
}
}
Finally, it is useful to be able to fetch the contents of a File
as a String
. While scala.io.Source
provides a convenient method for easily obtaining the contents of a File
, the close
method must be used on the Source
to release the underlying JVM and file system handles. If this isn't done, then the resource isn't released until the JVM GC (Garbage Collector) gets around to releasing the Source
instance itself. And even then, there is only a weak JVM guarantee the finalize
method will be called by the GC to close
the resource. This means that it is the client's responsibility to explicitly call the close
method, just the same as it is the responsibility of a client to tall close
on an instance of java.lang.AutoCloseable
. For this, we need a second definition of the using method which handles scala.io.Source
.
Here's the code for this (still not being concise):
def tryUsingSource[S <: scala.io.Source, R]
(instantiateSource: () => S)
(transfer: S => scala.util.Try[R])
: scala.util.Try[R] =
Try(instantiateSource())
.flatMap(
source => {
var optionExceptionTry: Option[Exception] = None
try
transfer(source)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
source.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
And here is an example usage of it in a super simple line streaming file reader (currently using to read tab-delimited files from database output):
def tryProcessSource(
file: java.io.File
, parseLine: (String, Int) => List[String] = (line, index) => List(line)
, filterLine: (List[String], Int) => Boolean = (values, index) => true
, retainValues: (List[String], Int) => List[String] = (values, index) => values
, isFirstLineNotHeader: Boolean = false
): scala.util.Try[List[List[String]]] =
tryUsingSource(scala.io.Source.fromFile(file)) {
source =>
scala.util.Try(
( for {
(line, index) <-
source.getLines().buffered.zipWithIndex
values =
parseLine(line, index)
if (index == 0 && !isFirstLineNotHeader) || filterLine(values, index)
retainedValues =
retainValues(values, index)
} yield retainedValues
).toList //must explicitly use toList due to the source.close which will
//occur immediately following execution of this anonymous function
)
)
An updated version of the above function has been provided as an answer to a different but related StackOverflow question.
Now, bringing that all together with the imports extracted (making it much easier to paste into Scala Worksheet present in both Eclipse ScalaIDE and IntelliJ Scala plugin to make it easy to dump output to the desktop to be more easily examined with a text editor), this is what the code looks like (with increased conciseness):
import scala.io.Source
import scala.util.Try
import java.io.{BufferedWriter, FileWriter, File, PrintWriter}
val defaultBufferSize: Int = 65536
def tryUsingAutoCloseable[A <: AutoCloseable, R]
(instantiateAutoCloseable: () => A) //parameter list 1
(transfer: A => scala.util.Try[R]) //parameter list 2
: scala.util.Try[R] =
Try(instantiateAutoCloseable())
.flatMap(
autoCloseable => {
var optionExceptionTry: Option[Exception] = None
try
transfer(autoCloseable)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
autoCloseable.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
def tryUsingSource[S <: scala.io.Source, R]
(instantiateSource: () => S)
(transfer: S => scala.util.Try[R])
: scala.util.Try[R] =
Try(instantiateSource())
.flatMap(
source => {
var optionExceptionTry: Option[Exception] = None
try
transfer(source)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
source.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
def tryPrintToFile(
lines: List[String],
location: File,
bufferSize: Int = defaultBufferSize
): Try[Unit] =
tryUsingAutoCloseable(() => new FileWriter(location)) { fileWriter =>
tryUsingAutoCloseable(() => new BufferedWriter(fileWriter, bufferSize)) { bufferedWriter =>
tryUsingAutoCloseable(() => new PrintWriter(bufferedWriter)) { printWriter =>
Try(lines.foreach(line => printWriter.println(line)))
}
}
}
def tryWriteToFile(
content: String,
location: File,
bufferSize: Int = defaultBufferSize
): Try[Unit] =
tryUsingAutoCloseable(() => new FileWriter(location)) { fileWriter =>
tryUsingAutoCloseable(() => new BufferedWriter(fileWriter, bufferSize)) { bufferedWriter =>
Try(bufferedWriter.write(content))
}
}
def tryProcessSource(
file: File,
parseLine: (String, Int) => List[String] = (line, index) => List(line),
filterLine: (List[String], Int) => Boolean = (values, index) => true,
retainValues: (List[String], Int) => List[String] = (values, index) => values,
isFirstLineNotHeader: Boolean = false
): Try[List[List[String]]] =
tryUsingSource(() => Source.fromFile(file)) { source =>
Try(
( for {
(line, index) <- source.getLines().buffered.zipWithIndex
values = parseLine(line, index)
if (index == 0 && !isFirstLineNotHeader) || filterLine(values, index)
retainedValues = retainValues(values, index)
} yield retainedValues
).toList
)
}
As a Scala/FP newbie, I've burned many hours (in mostly head-scratching frustration) earning the above knowledge and solutions. I hope this helps other Scala/FP newbies get over this particular learning hump faster.

- 5,661
- 8
- 53
- 86
-
2Incredible update. The only problem is that now you have like 100 lines of code which could be replaced with `try-catch-finally`. Still love your passion. – Observer Sep 26 '16 at 11:31
-
1@Observer I would assert that is an inaccurate statement. The pattern I am describing is actually reducing the amount of boilerplate a _client_ must write to ensure proper handling of closing of AutoCloseables while also enabling the Scala idiomatic FP pattern of using scala.util.Try. If you attempt to achieve the same effects I have by manually writing out the try/catch/finally blocks, I think you will find you end up with quite a bit more boilerplate than you are imagining. So, there is significant readability value in pushing all the boilerplate into the 100 lines of Scala function. – chaotic3quilibrium Sep 26 '16 at 14:33
-
1Sorry if that sounded offensive in any way. Still, my point is that there is no need in such amount of code, because the same could be achieved through non-functional approach with much more simplicity. Personally, I'd write try-finally with some additional checks. It's just shorter. If I wanted to use wrappers, ApacheUtils are there to use all the dirty work. More, all standard Reader/Writers do close underlying streams so your multipwrap is not needed. P.S. : I've changed my vote from minus one to plus one to support your efforts. So, please, don't suspect me in a bad intentions. – Observer Sep 26 '16 at 15:48
-
-
Remember, you are required to meet the explicit contract of AutoCloseable _regardless_ of how some implementations happen to work right now (ex: Java.io.Reader). The method I designed honors that requirement. Consider that at some point in the future, Reader was changed such that you could no longer depend upon it chaining dependent resource closes. And that is a completely valid design change per the AutoCloseable contract. – chaotic3quilibrium Sep 26 '16 at 16:07
-
Then, any code using my method above remains functioning and stable. However, any code which left out the close on dependent resources (knowing about the _old_ Java.io.Reader implementation) would have a resource leak and then have to be revisited and refactored. This is why adhering to explicit interface contracts is such a high value. – chaotic3quilibrium Sep 26 '16 at 16:15
-
1I understand your point of view. Thanks for discussion, I have to think about it a bit. Have a nice day! – Observer Sep 26 '16 at 16:47
Here's an example of writing some lines to a file using scalaz-stream.
import scalaz._
import scalaz.stream._
def writeLinesToFile(lines: Seq[String], file: String): Task[Unit] =
Process(lines: _*) // Process that enumerates the lines
.flatMap(Process(_, "\n")) // Add a newline after each line
.pipe(text.utf8Encode) // Encode as UTF-8
.to(io.fileChunkW(fileName)) // Buffered write to the file
.runLog[Task, Unit] // Get this computation as a Task
.map(_ => ()) // Discard the result
writeLinesToFile(Seq("one", "two"), "file.txt").run

- 30,334
- 10
- 78
- 137
To surpass samthebest and the contributors before him, I have improved the naming and conciseness:
def using[A <: {def close() : Unit}, B](resource: A)(f: A => B): B =
try f(resource) finally resource.close()
def writeStringToFile(file: File, data: String, appending: Boolean = false) =
using(new FileWriter(file, appending))(_.write(data))

- 903
- 11
- 17
-
This uses "duck typing" which depends upon reflection. For many contexts, depending upon reflection is a non-starter. – chaotic3quilibrium Mar 15 '18 at 18:25
No dependencies, with error handling
- Uses methods from the standard library exclusively
- Creates directories for the file, if necessary
- Uses
Either
for error handling
Code
def write(destinationFile: Path, fileContent: String): Either[Exception, Path] =
write(destinationFile, fileContent.getBytes(StandardCharsets.UTF_8))
def write(destinationFile: Path, fileContent: Array[Byte]): Either[Exception, Path] =
try {
Files.createDirectories(destinationFile.getParent)
// Return the path to the destinationFile if the write is successful
Right(Files.write(destinationFile, fileContent))
} catch {
case exception: Exception => Left(exception)
}
Usage
val filePath = Paths.get("./testDir/file.txt")
write(filePath , "A test") match {
case Right(pathToWrittenFile) => println(s"Successfully wrote to $pathToWrittenFile")
case Left(exception) => println(s"Could not write to $filePath. Exception: $exception")
}

- 32,039
- 22
- 142
- 171
2019 Update:
Summary - Java NIO (or NIO.2 for async) is still the most comprehensive file processing solution supported in Scala. The following code creates and writes some text to a new file:
import java.io.{BufferedOutputStream, OutputStream}
import java.nio.file.{Files, Paths}
val testFile1 = Paths.get("yourNewFile.txt")
val s1 = "text to insert in file".getBytes()
val out1: OutputStream = new BufferedOutputStream(
Files.newOutputStream(testFile1))
try {
out1.write(s1, 0, s1.length)
} catch {
case _ => println("Exception thrown during file writing")
} finally {
out1.close()
}
- Import Java libraries: IO and NIO
- Create a
Path
object with your chosen file name - Convert your text that you want to insert into a file into a byte array
- Get your file as a stream:
OutputStream
- Pass your byte array into your output stream's
write
function - Close the stream

- 3,203
- 35
- 32
Similar to this answer, here is an example with fs2
(version 1.0.4):
import cats.effect._
import fs2._
import fs2.io
import java.nio.file._
import scala.concurrent.ExecutionContext
import scala.language.higherKinds
import cats.syntax.functor._
object ScalaApp extends IOApp {
def write[T[_]](p: Path, s: String)
(implicit F: ConcurrentEffect[T], cs: ContextShift[T]): T[Unit] = {
Stream(s)
.covary[T]
.through(text.utf8Encode)
.through(
io.file.writeAll(
p,
scala.concurrent.ExecutionContext.global,
Seq(StandardOpenOption.CREATE)
)
)
.compile
.drain
}
def run(args: List[String]): IO[ExitCode] = {
implicit val executionContext: ExecutionContext =
scala.concurrent.ExecutionContext.Implicits.global
implicit val contextShift: ContextShift[IO] =
IO.contextShift(executionContext)
val outputFile: Path = Paths.get("output.txt")
write[IO](outputFile, "Hello world\n").as(ExitCode.Success)
}
}

- 2,781
- 2
- 12
- 32
import java.io.File
import java.io.PrintWriter
val file = new File("tmp/cloudwatch/metric.json")
val writer = new PrintWriter(file);
writer.write(stream);
writer.close();
Worked for me

- 71
- 1
- 3
This line helps to write a file from an Array or String.
new PrintWriter(outputPath) { write(ArrayName.mkString("")); close }

- 163
- 3
- 5
- 18
If you are anyways having Akka Streams in your project, it provides a one-liner:
def writeToFile(p: Path, s: String)(implicit mat: Materializer): Unit = {
Source.single(ByteString(s)).runWith(FileIO.toPath(p))
}
Akka docs > Streaming File IO

- 17,018
- 15
- 95
- 120