Mirroring Console Output to a File

Mirroring console output to a file

This may be some kind of more work, but I would go the other way round.

Instantiate a TraceListener for the console and one for the log file; thereafter use Trace.Write statements in your code instead of Console.Write. It becomes easier afterwards to remove the log, or the console output, or to attach another logging mechanism.

static void Main(string[] args)
{
Trace.Listeners.Clear();

TextWriterTraceListener twtl = new TextWriterTraceListener(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName));
twtl.Name = "TextLogger";
twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;

ConsoleTraceListener ctl = new ConsoleTraceListener(false);
ctl.TraceOutputOptions = TraceOptions.DateTime;

Trace.Listeners.Add(twtl);
Trace.Listeners.Add(ctl);
Trace.AutoFlush = true;

Trace.WriteLine("The first line to be in the logfile and on the console.");
}

As far as I can recall, you can define the listeners in the application configuration making it possible to activate or deactivate the logging without touching the build.

How to Save Console.WriteLine Output to Text File

Try this example from this article - Demonstrates redirecting the Console output to a file

using System;
using System.IO;

static public void Main ()
{
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream ("./Redirect.txt", FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter (ostrm);
}
catch (Exception e)
{
Console.WriteLine ("Cannot open Redirect.txt for writing");
Console.WriteLine (e.Message);
return;
}
Console.SetOut (writer);
Console.WriteLine ("This is a line of text");
Console.WriteLine ("Everything written to Console.Write() or");
Console.WriteLine ("Console.WriteLine() will be written to a file");
Console.SetOut (oldOut);
writer.Close();
ostrm.Close();
Console.WriteLine ("Done");
}

Java: How to mirror console output to file

Capture System.out before changing it, and use TeeOutputStream:

OutputStream myCaptureStream = ...;
PrintStream original = System.out;
OutptStream outputtee = new TeeOutputStream(originalOut, myCaptureStream);
PrintStream printTee = new PrintStream(outputTee);
System.setOut(printTee);

Convert output stream (myCaptureStream) to an input stream

  • Use Java standard library PipedOutputStream: new PipedOutputStream; read carefully - you'll need your reader running on another thread.
  • Convert the input stream to a Reader,
  • and that to a BufferedReader.

BufferedReader gives you a readLine method.

Pseudo code:

// Feed myCaptureStream to TeeOutputStream
OutputStream myCaptureStream = new PipedOutputStream();

// Prepare to capture data being written to that output stream
InputStream myCaptureAsInputStream = new PipedInputStream(myCaptureStream);
Reader myCaptureReader = new InputStreamReader(myCaptureAsInputStream);
BufferedReader myCaptureBuffered = new BufferedReader(myCaptureReader, 1024);

// This must run on separate reader thread; in spin loop:
myCaptureBuffer.readLine

Copy all lines of a console app screen to text file

You can either:

1- Redirect Console.WriteLine to a file:

System.IO.FileStream fs = new System.IO.FileStream(@"C:\Output.txt", System.IO.FileMode.Create);
System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);
System.Console.SetOut(sw);

(PS. If you do so, don't forget to set the Console output back and close the stream before the program terminates)

2- When running your executable, direct the output to a file, for example:

C:\>MyExecutable.exe > C:\Output.txt

Can i mirror the console output to a website?

In order to intercept the output normally going to the console (or the standard output) you need to use the following API somewhere in your code:

System.setOut(myStream); 
System.setErr(myStream); //If you want to grab the error stream also. Could go do a different location

Many log libraries can already do this for you. But this is basically how you need to capture the output. What 'myStream' actually does is up to you. The quickest route to get this out to a web server on http://localhost:8888 is to direct the output to a file and start the JDK's embedded web server. Here is an example you should be able to run:

package test.example;

import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SystemOutToWeb
{
public static void main(String... args ) throws Exception
{
final Path myOutputFile = Paths.get("./MyOutputFile.txt");
final PrintStream myStream = new PrintStream(myOutputFile.toFile());

System.out.println("Going to redirect to : " + myOutputFile.toAbsolutePath());

System.setOut(myStream);
System.setErr(myStream);

System.out.println("Starting the Output");

//Have something that logs every 5 seconds
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() ->
{
System.out.println("Hello - the time is now " + Instant.now());
}, 1, 5, TimeUnit.SECONDS);

// Start the simple Java Built in Web Server.
final HttpServer http = HttpServer.create(new InetSocketAddress(8888), 0);
final HttpContext context = http.createContext("/");
context.setHandler(exchange ->
{
byte[] data = Files.readAllBytes(myOutputFile);
exchange.sendResponseHeaders(200, data.length);
OutputStream os = exchange.getResponseBody();
os.write(data);
os.close();
});
http.start();

}
}

If you give it a few seconds to run, then you should be able to see something at http://localhost:8888.

Of course, this is only the starting point. You could for instance use a different web server all together or augment this resource with some CSS further (perhaps even use a web socket to stream the file out as it updates).

Saving the console application screen in .txt file

You can only assign one output stream to the console. So you will need a stream that does both, writing to the screen and to a file.

You can always get standard output stream of the console like this:

Stream consoleOutput = Console.GetStandardOutput();

If you want to use multiple outputs, you have to create a new stream class that will distribute the data to multiple streams. For that you will have to overwrite the Stream class (not a full implementation, you will have to implement all other abstract members of Stream, too):

public class MultiStream : Stream {
private readonly Stream[] m_children;

public MultiStream(params Stream[] children) {
m_children = children;
}

public override Write(byte[] buffer, int offset, int count) {
foreach(Stream child in m_children) {
child.Write(buffer, offset, count);
}
}

//...
}

Now you can use your MultiStream to route your output to multiple streams:

        FileStream filestream = new FileStream("notepad.txt", FileMode.Create);
MultiStream outStream = new MultiStream(filestream, Console.GetStandardOutput());
var streamwriter = new StreamWriter(outStream);

If you are OK to replace Console.WriteLine, you could use a simpler way (assuming your streamwriter variable is accessible):

public void WriteLineToScreenAndFile(string text) {
Console.WriteLine(text);
streamwriter.WriteLine(text);
}

You can replace all calls to Console.WriteLine with a call to that method.



Related Topics



Leave a reply



Submit