Home | FAQ | Contact me

stdout Redirection in Java

Here's an example of how to redirect stdout to a file in Java while not sacrificing output to the console simultaneously.

package com.etretatlogiciels.utilities;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

/**
 * Quick way to redirect stdout to a file while, optionally, keeping the console
 * open. Fail means that System.out is untouched (everything will continue to go
 * to the console).
 * @author Russell Bateman
 * @since May 2015
 */
public class RedirectSystemOutStream
{
  /**
   * Redirect stdout to a file. Will print to stdout the state of what's going on
   * or not as desired. Will not fail quietly. Fail means that System.out is
   * untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   */
  public static void redirectSystemOutToFile( String outputFilepath )
  {
    redirectSystemOutToFile( outputFilepath, false, true );
  }

  /**
   * Redirect stdout to a file. Will print to stdout the state of what's going on
   * or not as desired. Will not fail quietly. Fail means that System.out is
   * untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   * @param hush false if output is to go simultaneously to stdout.
   */
  public static void redirectSystemOutToFile( String outputFilepath, boolean hush )
  {
    redirectSystemOutToFile( outputFilepath, hush, true );
  }

  /**
   * Redirect stdout to a file. Will print to stdout the state of what's going on
   * or not as desired. Will fail quietly if desired. Fail means that System.out is
   * untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   * @param quiet false if output is to go simultaneously to stdout.
   * @param hush if true, also do not print the final state and fail to do any of this quietly.
   */
  public static void redirectSystemOutToFile( String outputFilepath, boolean quiet, boolean hush )
  {
    if( outputFilepath == null )
      return;

    try
    {
      PrintStream console = System.out;
      PrintStream output  = new PrintStream( new FileOutputStream( new File( outputFilepath ) ) );

      if( !hush )
      {
        if( !quiet )
        {
          System.out.println( "Output will go to " + outputFilepath );
          System.out.println( "    ...as well as to the console" );
        }
      }

      System.setOut( output );

      if( !quiet )
        System.setOut( console );
    }
    catch( FileNotFoundException e )
    {
      if( !hush )
      {
        System.err.println( "Could not open output file; output will go to stdout." );
        e.printStackTrace();
      }
    }
  }

  /**
   * Redirect stdout to a file and to the console. Will fail quietly if desired. Fail
   * means that System.out is untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   */
  public static void redirectSystemOutToFileAndConsole( String outputFilepath )
  {
    redirectSystemOutToFileAndConsole( outputFilepath, false, false );
  }

  /**
   * Redirect stdout to a file and to the console. Will fail quietly if desired. Fail
   * means that System.out is untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   * @param hush false if output is to go simultaneously to stdout.
   */
  public static void redirectSystemOutToFileAndConsole( String outputFilepath, boolean quiet )
  {
    redirectSystemOutToFileAndConsole( outputFilepath, quiet, false );
  }

  /**
   * Redirect stdout to a file and to the console. Will fail quietly if desired. Fail
   * means that System.out is untouched (everything will continue to go to the console).
   * @param outputFilepath file pathname.
   * @param quiet false if output is to go simultaneously to stdout.
   * @param hush if true, also do not print the final state and fail to do any of this quietly.
   */
  public static void redirectSystemOutToFileAndConsole( String outputFilepath, boolean quiet, boolean hush )
  {
    try
    {
      FileOutputStream  fout     = new FileOutputStream( outputFilepath );
      MultiOutputStream multiOut = new MultiOutputStream( System.out, fout );
      PrintStream       stdout   = new PrintStream( multiOut );

      System.setOut( stdout );
    }
    catch( FileNotFoundException ex )
    {
      System.err.println( "Could not open output file; output will go do stdout." );
    }
  }

  public static void closeSystemOutFileAndConsole()
  {
    System.out.close();
  }

  static class MultiOutputStream extends OutputStream
  {
    OutputStream[] outputStreams;

    public MultiOutputStream( OutputStream... outputStreams )
    {
      this.outputStreams = outputStreams;
    }

    @Override
    public void write( int b ) throws IOException
    {
      for( OutputStream out : outputStreams )
        out.write( b );
    }

    @Override
    public void write( byte[] b ) throws IOException
    {
      for( OutputStream out : outputStreams )
        out.write( b );
    }

    @Override
    public void write( byte[] b, int off, int len ) throws IOException
    {
      for( OutputStream out : outputStreams )
        out.write( b, off, len );
    }

    @Override
    public void flush() throws IOException
    {
      for( OutputStream out : outputStreams )
        out.flush();
    }

    @Override
    public void close() throws IOException
    {
      for( OutputStream out : outputStreams )
        out.close();
    }
  }
}