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
What Is the Worst Gotcha in C# or .Net
Are There Any Suggestions for Developing a C# Coding Standards/Best Practices Document
Super-Simple Example of C# Observer/Observable with Delegates
What Is the Best Scripting Language to Embed in a C# Desktop Application
Accessing Google Spreadsheets with C# Using Google Data API
How to Have an Enum Bound Combobox with Custom String Formatting for Enum Values
Differencebetween Int, Int16, Int32 and Int64
Verifying That a String Contains Only Letters in C#
Linq .Any VS .Exists - What's the Difference
Convert.Changetype() Fails on Nullable Types
Hashing Passwords with Md5 or Sha-256 C#
Validation Error Style in Wpf, Similar to Silverlight
How to Get the Name of the Current Executable in C#
Admin Rights for a Single Method
How to Execute an Ssis Package from .Net
Is There an Alternative to Bastard Injection? (Aka Poor Man's Injection via Default Constructor)