System.out to a file in java
Asked Answered
T

7

60

I'm running an application from inside another one for testing purposes. I want to redirect the output for the tested app to a file, so I can have a log after each test.

Is there a way to redirect the output of an app to a file from the command line in java?

Thomasenathomasin answered 17/5, 2010 at 17:24 Comment(1)
it's most likely going to be a solution external with respect to Java VM, like file descriptors redirection in bash/sh (e.g. "app.exe > file.log 2>&1"), unless you use some configurable logging libraryCommunitarian
E
84

You can use the output stream redirector that is supported by the Windows command line, *nix shells , e.g.

java -jar myjar.jar > output.txt

Alternatively, as you are running the app from inside the vm, you could redirect System.out from within java itself. You can use the method

System.setOut(PrintStream ps)

Which replaces the standard output stream, so all subsequent calls to System.out go to the stream you specify. You could do this before running your wrapped application, e.g. calling System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("output.txt"))));

If you are using a wrapper that you can't modify, then create your own wrapper. So you have FEST wrapper -> stream redirector wrapper -> tested app.

For example, you can implement a simple wrapper like this:

public class OutputRedirector
{
   /* args[0] - class to launch, args[1]/args[2] file to direct System.out/System.err to */
   public static void main(String[] args) throws Exception
   {  // error checking omitted for brevity
      System.setOut(outputFile(args(1));
      System.setErr(outputFile(args(2));
      Class app = Class.forName(args[0]);
      Method main = app.getDeclaredMethod("main", new Class[] { (new String[1]).getClass()});
      String[] appArgs = new String[args.length-3];
      System.arraycopy(args, 3, appArgs, 0, appArgs.length);
      main.invoke(null, appArgs);
   }
   protected PrintStream outputFile(String name) {
       return new PrintStream(new BufferedOutputStream(new FileOutputStream(name)), true);
   }
}

You invoke it with 3 additional params - the Main class to run, and the output/error directs.

Evette answered 17/5, 2010 at 17:27 Comment(6)
And to be clear, this has nothing to do with java itself, but is a standard facility offered by the shell.Biarritz
I tried doing that but I end up with an empty txt file. The out put is still going to the terminal. The thing is that I'm using a helping class from a testing library called FEST (fest.easytesting.org). This helping class accepts parameters that it then can pass to the app. The stream redirector might no quite fit in hereThomasenathomasin
@Evette - see comment (as post below) by psu for answer repair.Tyrolienne
Parentheses in place of brackets being used on the input args :(Clino
I need to set autoflushing to true as pointed out here https://mcmap.net/q/325345/-system-out-to-a-file-in-javaLuvenialuwana
also you can replace > with >> if you want to append to file instead of overwriteLemar
I
53

When using this constructor:

new PrintStream(new BufferedOutputStream(new FileOutputStream("file.txt")));

remember to set autoflushing to true, i.e.:

new PrintStream(new BufferedOutputStream(new FileOutputStream("file.txt")), true);

otherwise you may get empty files even after your program finishes.

Indeliberate answered 13/11, 2012 at 9:26 Comment(3)
@ben There is a constructor on PrintStream that supports automatic flushing.Magnetomotive
@Magnetomotive I see that. However my comment was referring to a part of the answer that was modified after I made my comment. See also the edit history of the answer.Zoosporangium
@Zoosporangium Ok, got it. It initially misled me however when arriving at this answer from search results. Maybe the comment should be deleted now as it has served its purpose?Magnetomotive
F
30

Yes you can set your desired file like this.

try {
    System.setOut(new PrintStream(new File("output-file.txt")));
} catch (Exception e) {
     e.printStackTrace();
}
Frolicsome answered 17/5, 2010 at 17:34 Comment(1)
I know this is a very old thread. Can someone please explain the difference between System.setOut(new PrintStream(new File("output-file.txt"))); and new PrintStream(new BufferedOutputStream(new FileOutputStream("output-file.txt")), true); ? Why would one choose over the other? Apologies if I am asking something naive, however I do not see any difference. I am using JDK8Dedicate
Y
11

System.out.println() is used to print messages on the console.

System is a class defined in the java.lang package. out is an instance of PrintStream, which is a public and static member of the class System. As all instances of PrintStream class have a public method println().

System.out is a static PrintStream that writes to the console. We can redirect the output to a different PrintStream using the System.setOut() method which takes a PrintStream as a parameter.

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

public class SetPrintStream {
  public static void main(String[] args) throws FileNotFoundException{
           System.out.println("Print on console");

           // Store console print stream.
           PrintStream ps_console = System.out;

           File file = new File("file.txt");
           FileOutputStream fos = new FileOutputStream(file);

           // Create new print stream for file.
           PrintStream ps = new PrintStream(fos);

           // Set file print stream.
           System.setOut(ps);
           System.out.println("Print in the file !!");

           // Set console print stream.
           System.setOut(ps_console);
           System.out.println("Console again !!");
 }
}

Output:
Print on console
Console again !!
new file.txt will be created.

For more information see my blog:

http://javaexplorer03.blogspot.in/2016/02/how-do-i-redirect-standard-output-to.html

Yordan answered 3/3, 2016 at 5:1 Comment(0)
Z
7

In order to improve "vijay.shad" response I used the code bellow to direct the file to the Home Directory in Linux or MyDocuments in Windows.

    try {
        System.setOut(new PrintStream(new File(FileSystemView.getFileSystemView()
                .getDefaultDirectory().toString()
                + File.separator + "output-file.txt")));
    } catch (Exception e) {
         e.printStackTrace();
    }
Zsigmondy answered 27/2, 2012 at 21:59 Comment(0)
P
1
    File file = new File("xyz.txt");        
    PrintStream printStreamToFile = new PrintStream(file);
    System.setOut(printStreamToFile);
    System.out.println("Hello I am writing to File xyz.txt");
Prizewinner answered 17/8, 2016 at 10:6 Comment(0)
C
-3

Or you can use Class FileWriter.

Centime answered 17/5, 2010 at 17:27 Comment(1)
I don't think that's workable - the app is presently writing to System.outEvette

© 2022 - 2024 — McMap. All rights reserved.