Copying standard output to a file

I am trying to figure out how to copy standard output to a file while also having it continue to go to standard output. I can that with bash, but I want to do it within my Scala program (at the start of main) because that is where the desired output file name will be known. I found the following way to redirect standard output to a file in Java, but that stops it from going to standard output. Does anyone know a simple way to do this? Thanks.

PrintStream console = System.out;

File file = new File("out.txt");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setOut(ps);
System.out.println("This goes to out.txt");

System.setOut(console);
System.out.println("This goes to the console");

I found a link on how to solve this problem:

I may post the Scala version when I finish it.

I did this once by creating my own class MultiplexerOutputStream, which works something like this:

class MultiplexerOutputStream(delegates: Iterable[OutputStream]) extends OutputStream {

def write(b: Int): Unit = delegates.foreach(delegate => Try(delegate.write(b)))

}

Use something like this:

val file = new File(“out.txt”)

val fos = new FileOutputStream(file)

val mos = new MultiplexerOutputStream(Seq(System.out, fos))

val ps = new PrintStream(mos)

System.setOut(ps)

println(“Hello to console and file!”)

Just use Scribe (https://github.com/outr/scribe) and STOP USING System.out!

Thanks for that code. Does the file have to be manually closed?

I realize that scribe is more versatile than Standard.out, but it seems to me that the latter is still useful and convenient for basic monitoring of a program, particularly a long-running one. If I can take notes on my smart phone or computer, does that mean I should discard all notepads, pens, and pencils? What harm is done by using System.out?

It is standard practice to close files. If you don’t, probably the JVM will close it eventually.

I converted the original solution (posted in a link above) to Scala. It is similar to the code that you posted above. I noticed two things.

If I call it in main, it only seems to affect the standard output in main itself (not down the call stack). I want it to apply to all output for my entire program, so I moved the call to the object enclosing main.

I also noticed that I don’t seem to have to close the file. Usually when I neglect to close a file, the output is incomplete. Not sure why the difference here.

If you want to avoid reinvent the wheel, Apache Commons IO has a TeeOutputStream (and also TeeInputStream).

Sorry if this is dumb question, but where can I get the source code for TeeOutputStream? I’d like to see how it compares to my implementation. Thanks.

Here’s a git mirror if Apache’s source repository: https://github.com/apache/commons-io/blob/master/src/main/java/org/apache/commons/io/output/TeeOutputStream.java

Spark 2.* uses println to output Dataset.explain()