System.Out to a File in Java

System.out to a file in java

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.

Java writing to File or System.out

What you're trying to accomplish, is to treat the fileoutput and the consoleoutput the same. This is possible, because System.out is a PrintStream, and you can create a PrintStream for a file like this

new PrintStream(yourFile) 

or insert a BufferedOutputStream in between

new PrintStream(new BufferedOutputStream(new FileOutputStream(yourFile))).

Note that this is not needed, because PrintStream does buffer its output itself.

I would create a variable (global or not), representing the current output.
This might be a PrintStream, either System.out, or a PrintStream around a FileOutputStream, whatever you desire. You would then pass this stream to the write method or call the print methods on it directly.

The advantage is that you can easily switch this without much code modification, you can redirect it wherever you wan't. It's no problem to redirect it to a file and System.out! You wouldn't get that pure flexibility with the way you're writing the method currently.

You could (not saying you should), also redirect System.out directly, using System.setOut. This however is bad style, because it is quite uncommon and might confuse everyone else, if they have not seen the call to System.setOut.

Writing System.Out.Println into text file

System.out is a PrintStream that writes to the standard output. You need to create a FileOutputStream and decorates it with PrintStream (or better FileWriter with PrintWriter):

File file = new File("C:/file.txt");
FileWriter fw = new FileWriter(file);
PrintWriter pw = new PrintWriter(fw);
pw.println("Hello World");
pw.close();

Also see:

  • Which is the best way to create file and write to it in Java.

Show stdout in file and in console (with System.setOut(new PrintStream(new File(output-file.txt))

You could create a PrintWriter with an OutputStream that does both writes.

final OutputStream stdOut = System.out;
try {
System.setOut(new PrintStream(new OutputStream() {
private PrintStream ps = new PrintStream(new File("output-file.txt"));

@Override
public void write(int b) throws IOException {
ps.write(b);
stdOut.write(b);
}

@Override
public void flush() throws IOException {
super.flush();
ps.flush();
stdOut.flush();
}

@Override
public void close() throws IOException {
super.close();
ps.close();
// stdOut.close(); // Normally not done
}
}));
} catch (Exception e) {
e.printStackTrace();
}

System.out.println("Hello, world!");

Write all System.out into a file

What about System.setOut(PrintStream) ? You could insert this call in the initialization part of your program (start-up).

Was previously a commment:

And of course you can do the same with System.err - namely System.setErr(PrintStream), but better to a different file stream.

In detail assuming an autoflushing appending and buffered file stream:

    String file = ...;
PrintStream ps =
new PrintStream(true, new BufferedOutputStream(new FileOutputStream(file, true)));
System.setOut(ps);

Writing from System.out.println to a file

Every time you call WriteToFile.write, it reopens the file for writing, truncating the file's original contents. You should open the file once, in the constructor (and store the PrintWriter in a field), and add a close method that calls close for the PrintWriter.

On the calling side, do this:

WriteToFile writer = new WriteToFile(filename);
try {
// writer.write(...);
} finally {
writer.close();
}

By having the close call in a finally block, you ensure the file is closed even if an exception causes the function to quit early.

How to write console output to a txt file

You need to do something like this:

PrintStream out = new PrintStream(new FileOutputStream("output.txt"));
System.setOut(out);

The second statement is the key. It changes the value of the supposedly "final" System.out attribute to be the supplied PrintStream value.

There are analogous methods (setIn and setErr) for changing the standard input and error streams; refer to the java.lang.System javadocs for details.

A more general version of the above is this:

PrintStream out = new PrintStream(
new FileOutputStream("output.txt", append), autoFlush);
System.setOut(out);

If append is true, the stream will append to an existing file instead of truncating it. If autoflush is true, the output buffer will be flushed whenever a byte array is written, one of the println methods is called, or a \n is written.


I'd just like to add that it is usually a better idea to use a logging subsystem like Log4j, Logback or the standard Java java.util.logging subsystem. These offer fine-grained logging control via runtime configuration files, support for rolling log files, feeds to system logging, and so on.

Alternatively, if you are not "logging" then consider the following:

  • With typical shells, you can redirecting standard output (or standard error) to a file on the command line; e.g.

    $ java MyApp > output.txt   

    For more information, refer to a shell tutorial or manual entry.

  • You could change your application to use an out stream passed as a method parameter or via a singleton or dependency injection rather than writing to System.out.

Changing System.out may cause nasty surprises for other code in your JVM that is not expecting this to happen. (A properly designed Java library will avoid depending on System.out and System.err, but you could be unlucky.)



Related Topics



Leave a reply



Submit