Writing Console Output to .txt [duplicate] - c#

I have a program which outputs various results onto a command line console.
How do I save the output to a text file using a StreamReader or other techniques?
System.Collections.Generic.IEnumerable<String> lines = File.ReadAllLines(#"C:\Test\ntfs8.txt");
foreach (String r in lines.Skip(1))
{
String[] token = r.Split(',');
String[] datetime = token[0].Split(' ');
String timeText = datetime[4];
String actions = token[2];
Console.WriteLine("The time for this array is: " + timeText);
Console.WriteLine(token[7]);
Console.WriteLine(actions);
MacActions(actions);
x = 1;
Console.WriteLine("================================================");
}
if (x == 2)
{
Console.WriteLine("The selected time does not exist within the log files!");
}
System.IO.StreamReader reader = ;
string sRes = reader.ReadToEnd();
StreamWriter SW;
SW = File.CreateText("C:\\temp\\test.bodyfile");
SW.WriteLine(sRes);
SW.Close();
Console.WriteLine("File Created");
reader.Close();

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");
}

Try if this works:
FileStream filestream = new FileStream("out.txt", FileMode.Create);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);

For the question:
How to save Console.Writeline Outputs
to text file?
I would use Console.SetOut as others have mentioned.
However, it looks more like you are keeping track of your program flow. I would consider using Debug or Trace for keeping track of the program state.
It works similar the console except you have more control over your input such as WriteLineIf.
Debug will only operate when in debug mode where as Trace will operate in both debug or release mode.
They both allow for listeners such as output files or the console.
TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(tr1);
TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
Debug.Listeners.Add(tr2);
-http://support.microsoft.com/kb/815788

do you want to write code for that or just use command-line feature 'command redirection' as follows:
app.exe >> output.txt
as demonstrated here: http://discomoose.org/2006/05/01/output-redirection-to-a-file-from-the-windows-command-line/ (Archived at archive.org)
EDIT: link dead, here's another example: http://pcsupport.about.com/od/commandlinereference/a/redirect-command-output-to-file.htm

Based in the answer by WhoIsNinja:
This code will output both into the Console and into a Log string that can be saved into a file, either by appending lines to it or by overwriting it.
The default name for the log file is 'Log.txt' and is saved under the Application path.
public static class Logger
{
public static StringBuilder LogString = new StringBuilder();
public static void WriteLine(string str)
{
Console.WriteLine(str);
LogString.Append(str).Append(Environment.NewLine);
}
public static void Write(string str)
{
Console.Write(str);
LogString.Append(str);
}
public static void SaveLog(bool Append = false, string Path = "./Log.txt")
{
if (LogString != null && LogString.Length > 0)
{
if (Append)
{
using (StreamWriter file = System.IO.File.AppendText(Path))
{
file.Write(LogString.ToString());
file.Close();
file.Dispose();
}
}
else
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(Path))
{
file.Write(LogString.ToString());
file.Close();
file.Dispose();
}
}
}
}
}
Then you can use it like this:
Logger.WriteLine("==========================================================");
Logger.Write("Loading 'AttendPunch'".PadRight(35, '.'));
Logger.WriteLine("OK.");
Logger.SaveLog(true); //<- default 'false', 'true' Append the log to an existing file.

Create a class Logger(code below), replace Console.WriteLine with Logger.Out.
At the end write to a file the string Log
public static class Logger
{
public static StringBuilder LogString = new StringBuilder();
public static void Out(string str)
{
Console.WriteLine(str);
LogString.Append(str).Append(Environment.NewLine);
}
}

Use Console.SetOut to redirect to a TextWriter as described here:
http://msdn.microsoft.com/en-us/library/system.console.setout.aspx

Necromancing.
I usually just create a class, which I can wrap around main in an IDisposable.
So I can log the console output to a file without modifying the rest of the code.
That way, I have the output in both the console and for later reference in a text-file.
public class Program
{
public static async System.Threading.Tasks.Task Main(string[] args)
{
using (ConsoleOutputMultiplexer co = new ConsoleOutputMultiplexer())
{
// Do something here
System.Console.WriteLine("Hello Logfile and Console 1 !");
System.Console.WriteLine("Hello Logfile and Console 2 !");
System.Console.WriteLine("Hello Logfile and Console 3 !");
} // End Using co
System.Console.WriteLine(" --- Press any key to continue --- ");
System.Console.ReadKey();
await System.Threading.Tasks.Task.CompletedTask;
} // End Task Main
}
with
public class MultiTextWriter
: System.IO.TextWriter
{
protected System.Text.Encoding m_encoding;
protected System.Collections.Generic.IEnumerable<System.IO.TextWriter> m_writers;
public override System.Text.Encoding Encoding => this.m_encoding;
public override System.IFormatProvider FormatProvider
{
get
{
return base.FormatProvider;
}
}
public MultiTextWriter(System.Collections.Generic.IEnumerable<System.IO.TextWriter> textWriters, System.Text.Encoding encoding)
{
this.m_writers = textWriters;
this.m_encoding = encoding;
}
public MultiTextWriter(System.Collections.Generic.IEnumerable<System.IO.TextWriter> textWriters)
: this(textWriters, textWriters.GetEnumerator().Current.Encoding)
{ }
public MultiTextWriter(System.Text.Encoding enc, params System.IO.TextWriter[] textWriters)
: this((System.Collections.Generic.IEnumerable<System.IO.TextWriter>)textWriters, enc)
{ }
public MultiTextWriter(params System.IO.TextWriter[] textWriters)
: this((System.Collections.Generic.IEnumerable<System.IO.TextWriter>)textWriters)
{ }
public override void Flush()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Flush();
}
}
public async override System.Threading.Tasks.Task FlushAsync()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.FlushAsync();
}
await System.Threading.Tasks.Task.CompletedTask;
}
public override void Write(char[] buffer, int index, int count)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Write(buffer, index, count);
}
}
public override void Write(System.ReadOnlySpan<char> buffer)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Write(buffer);
}
}
public async override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.WriteAsync(buffer, index, count);
}
await System.Threading.Tasks.Task.CompletedTask;
}
public async override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory<char> buffer, System.Threading.CancellationToken cancellationToken = default)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.WriteAsync(buffer, cancellationToken);
}
await System.Threading.Tasks.Task.CompletedTask;
}
protected override void Dispose(bool disposing)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Dispose();
}
}
public async override System.Threading.Tasks.ValueTask DisposeAsync()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.DisposeAsync();
}
await System.Threading.Tasks.Task.CompletedTask;
}
public override void Close()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Close();
}
} // End Sub Close
} // End Class MultiTextWriter
public class ConsoleOutputMultiplexer
: System.IDisposable
{
protected System.IO.TextWriter m_oldOut;
protected System.IO.FileStream m_logStream;
protected System.IO.StreamWriter m_logWriter;
protected MultiTextWriter m_multiPlexer;
public ConsoleOutputMultiplexer()
{
this.m_oldOut = System.Console.Out;
try
{
this.m_logStream = new System.IO.FileStream("./Redirect.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
this.m_logWriter = new System.IO.StreamWriter(this.m_logStream);
this.m_multiPlexer = new MultiTextWriter(this.m_oldOut.Encoding, this.m_oldOut, this.m_logWriter);
System.Console.SetOut(this.m_multiPlexer);
}
catch (System.Exception e)
{
System.Console.WriteLine("Cannot open Redirect.txt for writing");
System.Console.WriteLine(e.Message);
return;
}
} // End Constructor
void System.IDisposable.Dispose()
{
System.Console.SetOut(this.m_oldOut);
if (this.m_multiPlexer != null)
{
this.m_multiPlexer.Flush();
if (this.m_logStream != null)
this.m_logStream.Flush();
this.m_multiPlexer.Close();
}
if(this.m_logStream != null)
this.m_logStream.Close();
} // End Sub Dispose
} // End Class ConsoleOutputMultiplexer

Using only configuration in your app.config:
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/>
<!--
<add name="logListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log" />
<add name="EventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="MyEventLog"/>
-->
<!--
Remove the Default listener to avoid duplicate messages
being sent to the debugger for display
-->
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
For testing, you can use DebugView before running the program, then we can easily view all of the log messages.
References:
http://blogs.msdn.com/b/jjameson/archive/2009/06/18/configuring-logging-in-a-console-application.aspx
http://www.thejoyofcode.com/from_zero_to_logging_with_system_diagnostics_in_15_minutes.aspx
Redirect Trace output to Console
Problem redirecting debug output to a file using trace listener
https://ukadcdiagnostics.codeplex.com/
http://geekswithblogs.net/theunstablemind/archive/2009/09/09/adventures-in-system.diagnostics.aspx

Related

Log user input in a c# console application as well as console out

I am currently trying to figure out, what´s the best way to log the user input as well as the output generated by the console.
My current approach is using :
class ConsoleCopy : IDisposable
{
FileStream fileStream;
StreamWriter fileWriter;
TextWriter doubleWriter;
TextWriter oldOut;
class DoubleWriter : TextWriter
{
TextWriter one;
TextWriter two;
public DoubleWriter(TextWriter one, TextWriter two)
{
this.one = one;
this.two = two;
}
public override Encoding Encoding
{
get { return one.Encoding; }
}
public override void Flush()
{
one.Flush();
two.Flush();
}
public override void Write(char value)
{
one.Write(value);
two.Write(value);
}
}
public ConsoleCopy(string path)
{
oldOut = Console.Out;
try
{
fileStream = File.Create(path);
fileWriter = new StreamWriter(fileStream);
fileWriter.AutoFlush = true;
doubleWriter = new DoubleWriter(fileWriter, oldOut);
}
catch (Exception e)
{
Console.WriteLine("Cannot open file for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(doubleWriter);
}
public void Dispose()
{
Console.SetOut(oldOut);
if (fileWriter != null)
{
fileWriter.Flush();
fileWriter.Close();
fileWriter = null;
}
if (fileStream != null)
{
fileStream.Close();
fileStream = null;
}
}
}
and
using (var cc = new ConsoleCopy(log))
{
//some code
Conole.WriteLine(string);
Console.WriteLine(string2);
string input = Console.ReadLine();
}
This approach is working fine for the console output, but I still can not figure out, how to add the user input.
I am redirecting the console output to the file while also being able to see it in the console. That is what I want to achieve with the uesr input aswell.
Thanks a lot!
The same way, actually.
Note that this class only implements ReadLine() for now:
class LoggingReader : TextReader
{
TextReader old;
TextWriter log;
public LoggingReader(TextReader old, TextWriter log)
{
this.old = old;
this.log = log;
}
public override string ReadLine()
{
string input = old.ReadLine();
log.Write("> {0}\r\n", input);
return input;
}
}
These are added to ConsoleCopy as members:
TextReader oldIn;
TextReader loggingReader;
Here is the new ConsoleCopy constructor:
public ConsoleCopy(string path)
{
oldOut = Console.Out;
oldIn = Console.In; // ADDED
try
{
fileStream = File.Create(path);
fileWriter = new StreamWriter(fileStream);
fileWriter.AutoFlush = true;
doubleWriter = new DoubleWriter(fileWriter, oldOut);
loggingReader = new LoggingReader(oldIn, fileWriter); // ADDED
}
catch (Exception e)
{
Console.WriteLine("Cannot open file for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(doubleWriter);
Console.SetIn(loggingReader); // ADDED
}
The log file contents:
This is output 1
This is output 2
> Test
Test command received
Enter to exit
>

Trap SOAP requests/response in C#

I am trying to trap the request/response xml of my soap communication. I would love to have used WCF, but must comply with the employer request.
So, I have this sample asmx website with this webmethod in my service:
[WebMethod]
public int Multiply(int x, int y)
{
return x * y;
}
The site is added to IIS and I can see it in browser:
http://localhost/WebService/Service.asmx?op=Multiply
and it works when I give it two int values.
I am trying to trap the SOAP body request that is getting sent and received. According to my research, if I add a soap extension, I would be able to do that. So, I am looking at this example: https://stackoverflow.com/a/10613433/1019042 and trying to imitate it.
I added a class library project to my solution with this class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services.Protocols;
using System.IO;
using System.Reflection;
namespace SoapExtensions
{
public class SoapLoggerExtension : SoapExtension
{
//private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Stream oldStream;
private Stream newStream;
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
WriteMessages("inside the getinitializer1");
return null;
}
public override object GetInitializer(Type serviceType)
{
WriteMessages("inside the getinitializer2");
WriteMessages("inside the getinitializer");
return null;
}
public override void Initialize(object initializer)
{
WriteMessages("inside the Initialize");
}
public override System.IO.Stream ChainStream(System.IO.Stream stream)
{
WriteMessages("inside the ChainStream");
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
public override void ProcessMessage(SoapMessage message)
{
WriteMessages("inside the ProcessMessage");
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
Log(message, "AfterSerialize");
CopyStream(newStream, oldStream);
newStream.Position = 0;
break;
case SoapMessageStage.BeforeDeserialize:
CopyStream(oldStream, newStream);
Log(message, "BeforeDeserialize");
break;
case SoapMessageStage.AfterDeserialize:
break;
}
}
private void WriteMessages(string message)
{
StreamWriter sw = new StreamWriter(#"C:\MyFolder\LogFolder\myLog.txt", true);
sw.WriteLine(message);
sw.Close();
}
public void Log(SoapMessage message, string stage)
{
newStream.Position = 0;
string contents = (message is SoapServerMessage) ? "SoapRequest " : "SoapResponse ";
contents += stage + ";";
StreamReader reader = new StreamReader(newStream);
contents += reader.ReadToEnd();
newStream.Position = 0;
WriteMessages(contents.ToString());
//log.Debug(contents);
}
void ReturnStream()
{
WriteMessages("inside the ReturnStream");
CopyAndReverse(newStream, oldStream);
}
void ReceiveStream()
{
WriteMessages("inside the ReceiveStream");
CopyAndReverse(newStream, oldStream);
}
public void ReverseIncomingStream()
{
WriteMessages("inside the ReverseIncomingStream");
ReverseStream(newStream);
}
public void ReverseOutgoingStream()
{
WriteMessages("inside the ReverseOutgoingStream");
ReverseStream(newStream);
}
public void ReverseStream(Stream stream)
{
WriteMessages("inside the ReverseStream");
TextReader tr = new StreamReader(stream);
string str = tr.ReadToEnd();
char[] data = str.ToCharArray();
Array.Reverse(data);
string strReversed = new string(data);
TextWriter tw = new StreamWriter(stream);
stream.Position = 0;
tw.Write(strReversed);
tw.Flush();
}
void CopyAndReverse(Stream from, Stream to)
{
WriteMessages("inside the CopyAndReverse");
TextReader tr = new StreamReader(from);
TextWriter tw = new StreamWriter(to);
string str = tr.ReadToEnd();
char[] data = str.ToCharArray();
Array.Reverse(data);
string strReversed = new string(data);
tw.Write(strReversed);
tw.Flush();
}
private void CopyStream(Stream fromStream, Stream toStream)
{
WriteMessages("inside the CopyStream");
try
{
StreamReader sr = new StreamReader(fromStream);
StreamWriter sw = new StreamWriter(toStream);
sw.WriteLine(sr.ReadToEnd());
sw.Flush();
}
catch (Exception ex)
{
string message = String.Format("CopyStream failed because: {0}", ex.Message);
WriteMessages("Message is: " + message);
WriteMessages("ex is: " + ex);
// log.Error(message, ex);
}
}
}
[AttributeUsage(AttributeTargets.Method)]
public class SoapLoggerExtensionAttribute : SoapExtensionAttribute
{
private int priority = 1;
public override int Priority
{
get { return priority; }
set { priority = value; }
}
public override System.Type ExtensionType
{
get { return typeof(SoapLoggerExtension); }
}
}
}
I added a message to every method just to see if anything gets called in my extension.
and then went to my service and added a reference to the project. I went to the web.config of the service and added this under system.web:
<webServices>
<soapExtensionTypes>
<add type="SoapExtensions.SoapLoggerExtension, SoapExtension"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>
The problem is that I don't get anything written in the mylog.txt like it is not hitting my soapservice.
The file resides in a folder that Everyone has full access to it.
Shouldn't the call to the Multiply log something via the soapextension? Are my settings wrong? Is there something else I should be doing?
I am using framework 3.5
try with
<webServices>
<soapExtensionTypes>
<add type="SoapExtensions.SoapLoggerExtension, SoapExtensions"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>
you're missing the 's' in the assembly name for the type.
Also, once you start up the browser at http://localhost/WebService/Service.asmx?op=Multiply, use Visual Studio and attach to the process.
This way, you can debug the incoming multiple call and trace through the flow. you'll see if the Extension point was hit.

How to send multiple images from android to a WCF Rest Service as a stream to write to a network drive?

After much googling and searching, I managed to send an image using multiparsers from android to my WCF service, but ideally, I'd like to send several images at once, instead of calling the method over and over again, since it'd take a lot longer, and add a bunch more overhead.
This is my current code
Android (Taken from code found on here somewhere):
public static String postFile(Bitmap bitmap, String urlString) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlString);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 30, bao);
byte[] data = bao.toByteArray();
//filename
String fileName = String.format("File_%d.png",new Date().getTime());
ByteArrayBody bab = new ByteArrayBody(data, fileName);
builder.addPart("image", bab);
final HttpEntity yourEntity = builder.build();
class ProgressiveEntity implements HttpEntity {
#Override
public void consumeContent() throws IOException {
yourEntity.consumeContent();
}
#Override
public InputStream getContent() throws IOException,
IllegalStateException {
return yourEntity.getContent();
}
#Override
public Header getContentEncoding() {
return yourEntity.getContentEncoding();
}
#Override
public long getContentLength() {
return yourEntity.getContentLength();
}
#Override
public Header getContentType() {
return yourEntity.getContentType();
}
#Override
public boolean isChunked() {
return yourEntity.isChunked();
}
#Override
public boolean isRepeatable() {
return yourEntity.isRepeatable();
}
#Override
public boolean isStreaming() {
return yourEntity.isStreaming();
} // CONSIDER put a _real_ delegator into here!
#Override
public void writeTo(OutputStream outstream) throws IOException {
class ProxyOutputStream extends FilterOutputStream {
/**
* #author Stephen Colebourne
*/
public ProxyOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(int idx) throws IOException {
out.write(idx);
}
public void write(byte[] bts) throws IOException {
out.write(bts);
}
public void write(byte[] bts, int st, int end) throws IOException {
out.write(bts, st, end);
}
public void flush() throws IOException {
out.flush();
}
public void close() throws IOException {
out.close();
}
} // CONSIDER import this class (and risk more Jar File Hell)
class ProgressiveOutputStream extends ProxyOutputStream {
public ProgressiveOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(byte[] bts, int st, int end) throws IOException {
// FIXME Put your progress bar stuff here!
out.write(bts, st, end);
}
}
yourEntity.writeTo(new ProgressiveOutputStream(outstream));
}
};
ProgressiveEntity myEntity = new ProgressiveEntity();
post.setEntity(myEntity);
HttpResponse response = client.execute(post);
return getContent(response);
}
public static String getContent(HttpResponse response) throws IOException {
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String body = "";
String content = "";
while ((body = rd.readLine()) != null)
{
content += body + "\n";
}
return content.trim();
}
C# WCF Service method to take it
[WebInvoke(UriTemplate = "UploadPicture/{filename}", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public String UploadPicture(string filename, Stream fileStream)
{
WriteLog("Uploading picture...");
try
{
MultipartParser parser = new MultipartParser(fileStream);
if (parser.Success)
{
string fileName = parser.Filename;
string contentType = parser.ContentType;
byte[] fileContent = parser.FileContents;
FileStream fileToupload = new FileStream("\\\\OHS-SUN\\Tracker\\robbie\\" + filename, FileMode.Create);
fileToupload.Write(fileContent, 0, fileContent.Length);
fileToupload.Close();
fileToupload.Dispose();
fileStream.Close();
return "Success !!!";
}
else
{
return "Exception!!!";
}
}
catch (Exception ex)
{
WriteLog("Uploading picture exception: " + ex.Message);
}
return "Picture uploaded!";
}
I'd like to go from sending one image, to sending several, each with 2 text attributes; the filename, and the project number they're associated with. Essentially, both is what I need it for. At the moment, I'm just trying to do put another addPart on to the android bit, but then I don't know how to add metadata to that and I wouldn't know how to parse it based on the name. I'm fine with using any third party libraries, the one I'm using on C# at the moment is already one.
Thanks a lot!
Instead of sending multiple images in one thing, I just stuck it in an asynchronous class and sent them concurrently with a max of 10 at a time until all the images are sent in that particular session. Seems to work fine, the implementation's the same, so I've not had to change any of that, which is good. If anyone would like me to post the code I did to do that, I'd be happy to. It's just small snippets here and there added to the above code, though.
Well, the main bit I added was:
public static class FileUploader extends AsyncTask<UploadFile , Void , String> implements Future<String>
{
#Override
protected void onPreExecute() {
filesUploading ++;
}
#Override
protected String doInBackground(UploadFile... uploadFile)
{
try
{
return postFile(uploadFile[0].file, uploadFile[0].projectNo, uploadFile[0].filename);
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
filesUploading --;
}
#Override
public boolean isDone() {
return AsyncTask.Status.FINISHED == getStatus();
}
}
This allows me to send each image separately, and handle them separately.

File being used by another process using StreamWriter

My program was practice for me, however, when I try to write all the directories it found, it crashes.
I tried the following:
Having it write to a file stream instead of the file itself
using File.Writealllines using a list<> (this worked, only it did the first five and no more)
FileStream.Write(subdir.ToCharArray())
I cannot see why this wouldn't work, what have I done wrong?
static void Main(string[] args)
{
Method(#"C:\");
}
static void Method(string dir)
{
//crash happens here v
StreamWriter sw = new StreamWriter(#"C:\users\"+Environment.UserName+"\desktop\log.txt",true);
foreach (string subdir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error");
}
}
sw.Close();
}
Its recursive.
Because you're calling Method again here:
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir); // BOOM
Your file is already open. You can't open it for writing again.
Open the file in Main once..
static void Main(string[] args) {
using (StreamWriter sw = new StreamWriter(#"C:\users\"+Environment.UserName+"\desktop\log.txt",true)) {
Method(#"C:\", sw);
}
}
Then accept it in your method:
public static void Method(string dir, StreamWriter sw) {
Then when you call it again:
sw.Write(subdir);
Method(subdir, sw); // pass in the streamwriter.
Note though, that you will quickly start chewing up memory. You're recursing through your entire C:\ drive. Maybe test it on a smaller folder?
I am agree with above but in my case solution different a little.
private static object locker = new object();
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
Because the following function is called asynchronous and asynchronous in many places in my asp.net core application. In this case, one thread was trying to write a file, another thread wanted to write the same file, and there was an error. As a solution, I tried the above, but it didn't work either because I tried to open a new stream before closing the previous stream. So I decided to write a secure block of code as a solution. In this case, since the other threads could not reach the locked area, they made the write operation by waiting for the previous operation and I was able to write the file without error.
I think; there is another reason code behind, cause i have used Singleton registration on startup. This function's caller classes are isolated from each other. with this reason they didn't know which thread is called the function before. Their lifetime has been finished while. Also FileStream wraps the StreamWriter then it also may work without lock, anyway it is guaranty.
Even Microsoft.Extensions.Logging does not support FileLoger by default, but we can write custom. I share the entire implementation below
public class FileLoger : ILogger
{
public static IHostingEnvironment _env;
private static object locker = new object();
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = string.Format("{0}: {1} - {2}", logLevel.ToString(), eventId.Id, formatter(state, exception));
WriteMessageToFile(message);
}
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
}
public class FileLogProvider : ILoggerProvider
{
public FileLogProvider(IHostingEnvironment env)
{
FileLoger._env = env;
}
public ILogger CreateLogger(string category)
{
return new FileLoger();
}
public void Dispose()
{
}
}
Seems you didn't close your streamwriter before you use it again
public static void Method(string dir)
{
//crash happens here v
StreamWriter sw = new StreamWriter(#"C:\users\"+Environment.UserName+"\desktop\log.txt",true);
foreach (string subdir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subdir);
sw.Write(subdir);
//This line you'll call "Method" again
Method(subdir);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error");
}
}
sw.Close();
}
Also, another suggestion, why don't you use "System.IO.File.AppendAllText(Path,Text)" method? it's easier to use

How to Save Console.WriteLine Output to Text File

I have a program which outputs various results onto a command line console.
How do I save the output to a text file using a StreamReader or other techniques?
System.Collections.Generic.IEnumerable<String> lines = File.ReadAllLines(#"C:\Test\ntfs8.txt");
foreach (String r in lines.Skip(1))
{
String[] token = r.Split(',');
String[] datetime = token[0].Split(' ');
String timeText = datetime[4];
String actions = token[2];
Console.WriteLine("The time for this array is: " + timeText);
Console.WriteLine(token[7]);
Console.WriteLine(actions);
MacActions(actions);
x = 1;
Console.WriteLine("================================================");
}
if (x == 2)
{
Console.WriteLine("The selected time does not exist within the log files!");
}
System.IO.StreamReader reader = ;
string sRes = reader.ReadToEnd();
StreamWriter SW;
SW = File.CreateText("C:\\temp\\test.bodyfile");
SW.WriteLine(sRes);
SW.Close();
Console.WriteLine("File Created");
reader.Close();
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");
}
Try if this works:
FileStream filestream = new FileStream("out.txt", FileMode.Create);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
For the question:
How to save Console.Writeline Outputs
to text file?
I would use Console.SetOut as others have mentioned.
However, it looks more like you are keeping track of your program flow. I would consider using Debug or Trace for keeping track of the program state.
It works similar the console except you have more control over your input such as WriteLineIf.
Debug will only operate when in debug mode where as Trace will operate in both debug or release mode.
They both allow for listeners such as output files or the console.
TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(tr1);
TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
Debug.Listeners.Add(tr2);
-http://support.microsoft.com/kb/815788
do you want to write code for that or just use command-line feature 'command redirection' as follows:
app.exe >> output.txt
as demonstrated here: http://discomoose.org/2006/05/01/output-redirection-to-a-file-from-the-windows-command-line/ (Archived at archive.org)
EDIT: link dead, here's another example: http://pcsupport.about.com/od/commandlinereference/a/redirect-command-output-to-file.htm
Based in the answer by WhoIsNinja:
This code will output both into the Console and into a Log string that can be saved into a file, either by appending lines to it or by overwriting it.
The default name for the log file is 'Log.txt' and is saved under the Application path.
public static class Logger
{
public static StringBuilder LogString = new StringBuilder();
public static void WriteLine(string str)
{
Console.WriteLine(str);
LogString.Append(str).Append(Environment.NewLine);
}
public static void Write(string str)
{
Console.Write(str);
LogString.Append(str);
}
public static void SaveLog(bool Append = false, string Path = "./Log.txt")
{
if (LogString != null && LogString.Length > 0)
{
if (Append)
{
using (StreamWriter file = System.IO.File.AppendText(Path))
{
file.Write(LogString.ToString());
file.Close();
file.Dispose();
}
}
else
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(Path))
{
file.Write(LogString.ToString());
file.Close();
file.Dispose();
}
}
}
}
}
Then you can use it like this:
Logger.WriteLine("==========================================================");
Logger.Write("Loading 'AttendPunch'".PadRight(35, '.'));
Logger.WriteLine("OK.");
Logger.SaveLog(true); //<- default 'false', 'true' Append the log to an existing file.
Create a class Logger(code below), replace Console.WriteLine with Logger.Out.
At the end write to a file the string Log
public static class Logger
{
public static StringBuilder LogString = new StringBuilder();
public static void Out(string str)
{
Console.WriteLine(str);
LogString.Append(str).Append(Environment.NewLine);
}
}
Use Console.SetOut to redirect to a TextWriter as described here:
http://msdn.microsoft.com/en-us/library/system.console.setout.aspx
Necromancing.
I usually just create a class, which I can wrap around main in an IDisposable.
So I can log the console output to a file without modifying the rest of the code.
That way, I have the output in both the console and for later reference in a text-file.
public class Program
{
public static async System.Threading.Tasks.Task Main(string[] args)
{
using (ConsoleOutputMultiplexer co = new ConsoleOutputMultiplexer())
{
// Do something here
System.Console.WriteLine("Hello Logfile and Console 1 !");
System.Console.WriteLine("Hello Logfile and Console 2 !");
System.Console.WriteLine("Hello Logfile and Console 3 !");
} // End Using co
System.Console.WriteLine(" --- Press any key to continue --- ");
System.Console.ReadKey();
await System.Threading.Tasks.Task.CompletedTask;
} // End Task Main
}
with
public class MultiTextWriter
: System.IO.TextWriter
{
protected System.Text.Encoding m_encoding;
protected System.Collections.Generic.IEnumerable<System.IO.TextWriter> m_writers;
public override System.Text.Encoding Encoding => this.m_encoding;
public override System.IFormatProvider FormatProvider
{
get
{
return base.FormatProvider;
}
}
public MultiTextWriter(System.Collections.Generic.IEnumerable<System.IO.TextWriter> textWriters, System.Text.Encoding encoding)
{
this.m_writers = textWriters;
this.m_encoding = encoding;
}
public MultiTextWriter(System.Collections.Generic.IEnumerable<System.IO.TextWriter> textWriters)
: this(textWriters, textWriters.GetEnumerator().Current.Encoding)
{ }
public MultiTextWriter(System.Text.Encoding enc, params System.IO.TextWriter[] textWriters)
: this((System.Collections.Generic.IEnumerable<System.IO.TextWriter>)textWriters, enc)
{ }
public MultiTextWriter(params System.IO.TextWriter[] textWriters)
: this((System.Collections.Generic.IEnumerable<System.IO.TextWriter>)textWriters)
{ }
public override void Flush()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Flush();
}
}
public async override System.Threading.Tasks.Task FlushAsync()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.FlushAsync();
}
await System.Threading.Tasks.Task.CompletedTask;
}
public override void Write(char[] buffer, int index, int count)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Write(buffer, index, count);
}
}
public override void Write(System.ReadOnlySpan<char> buffer)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Write(buffer);
}
}
public async override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.WriteAsync(buffer, index, count);
}
await System.Threading.Tasks.Task.CompletedTask;
}
public async override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory<char> buffer, System.Threading.CancellationToken cancellationToken = default)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.WriteAsync(buffer, cancellationToken);
}
await System.Threading.Tasks.Task.CompletedTask;
}
protected override void Dispose(bool disposing)
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Dispose();
}
}
public async override System.Threading.Tasks.ValueTask DisposeAsync()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
await thisWriter.DisposeAsync();
}
await System.Threading.Tasks.Task.CompletedTask;
}
public override void Close()
{
foreach (System.IO.TextWriter thisWriter in this.m_writers)
{
thisWriter.Close();
}
} // End Sub Close
} // End Class MultiTextWriter
public class ConsoleOutputMultiplexer
: System.IDisposable
{
protected System.IO.TextWriter m_oldOut;
protected System.IO.FileStream m_logStream;
protected System.IO.StreamWriter m_logWriter;
protected MultiTextWriter m_multiPlexer;
public ConsoleOutputMultiplexer()
{
this.m_oldOut = System.Console.Out;
try
{
this.m_logStream = new System.IO.FileStream("./Redirect.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
this.m_logWriter = new System.IO.StreamWriter(this.m_logStream);
this.m_multiPlexer = new MultiTextWriter(this.m_oldOut.Encoding, this.m_oldOut, this.m_logWriter);
System.Console.SetOut(this.m_multiPlexer);
}
catch (System.Exception e)
{
System.Console.WriteLine("Cannot open Redirect.txt for writing");
System.Console.WriteLine(e.Message);
return;
}
} // End Constructor
void System.IDisposable.Dispose()
{
System.Console.SetOut(this.m_oldOut);
if (this.m_multiPlexer != null)
{
this.m_multiPlexer.Flush();
if (this.m_logStream != null)
this.m_logStream.Flush();
this.m_multiPlexer.Close();
}
if(this.m_logStream != null)
this.m_logStream.Close();
} // End Sub Dispose
} // End Class ConsoleOutputMultiplexer
Using only configuration in your app.config:
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/>
<!--
<add name="logListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log" />
<add name="EventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="MyEventLog"/>
-->
<!--
Remove the Default listener to avoid duplicate messages
being sent to the debugger for display
-->
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
For testing, you can use DebugView before running the program, then we can easily view all of the log messages.
References:
http://blogs.msdn.com/b/jjameson/archive/2009/06/18/configuring-logging-in-a-console-application.aspx
http://www.thejoyofcode.com/from_zero_to_logging_with_system_diagnostics_in_15_minutes.aspx
Redirect Trace output to Console
Problem redirecting debug output to a file using trace listener
https://ukadcdiagnostics.codeplex.com/
http://geekswithblogs.net/theunstablemind/archive/2009/09/09/adventures-in-system.diagnostics.aspx

Categories

Resources