Copying standard output to a file

#1

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");
#2

I found a link on how to solve this problem:

I may post the Scala version when I finish it.

#3

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!”)

#4

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

#5

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

#6

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?

#7

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

#8

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.

#9

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

#10

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.

#11

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