C # कंसोल एप्लिकेशन में, टेक्स्ट आउटपुट को टेक्स्ट फ़ाइल में प्रदर्शित करने का स्मार्ट तरीका है?
वर्तमान में मैं एक ही स्ट्रिंग को दोनों में Console.WriteLine
और InstanceOfStreamWriter.WriteLine
एक लॉग विधि में पारित कर रहा हूं ।
जवाबों:
यह किसी और तरह का काम हो सकता है, लेकिन मैं दूसरे रास्ते पर जाऊंगा।
TraceListener
कंसोल के लिए तुरंत और लॉग फ़ाइल के लिए एक; इसके बाद Trace.Write
अपने कोड में बयानों का उपयोग करें Console.Write
। लॉग, या कंसोल आउटपुट को निकालना या किसी अन्य लॉगिंग तंत्र को संलग्न करना बाद में आसान हो जाता है।
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.");
}
जहां तक मैं याद कर सकता हूं, आप एप्लिकेशन कॉन्फ़िगरेशन में श्रोताओं को परिभाषित कर सकते हैं कि बिल्ड को छूने के बिना लॉगिंग को सक्रिय या निष्क्रिय करना संभव है।
यह एक साधारण वर्ग है जो टेक्स्टविरिटर को उपविभाजित करता है ताकि इनपुट को फ़ाइल और कंसोल दोनों पर पुनर्निर्देशित किया जा सके।
इसे इस तरह इस्तेमाल करें
using (var cc = new ConsoleCopy("mylogfile.txt"))
{
Console.WriteLine("testing 1-2-3");
Console.WriteLine("testing 4-5-6");
Console.ReadKey();
}
यहाँ वर्ग है:
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;
}
}
}
Console.WriteLine()
, जो कि वास्तव में मैं चाहता था।
Console.SetOut(doubleWriter);
। जो कंसोल के लिए एक वैश्विक संशोधन कर रहा है, यह मुझे थोड़ा सा लगा, क्योंकि मैं उन अनुप्रयोगों में काम करने के लिए अभ्यस्त हूं जहां व्यावहारिक रूप से कुछ भी वैश्विक नहीं है। अच्छी चीज़!
Log4net की जाँच करें । Log4net के साथ आप कंसोल और फाइल एपेंडर्स सेट कर सकते हैं जो एक लॉग स्टेटमेंट के साथ दोनों जगहों पर लॉग मैसेज को आउटपुट कर सकते हैं।
क्या आप केवल >
कमांड का उपयोग करके किसी फ़ाइल में आउटपुट को रीडायरेक्ट नहीं कर सकते हैं ?
c:\>Console.exe > c:/temp/output.txt
यदि आपको दर्पण की आवश्यकता है, तो आप एक win32 संस्करण ढूंढ सकते हैं tee
कि किसी फ़ाइल में आउटपुट को विभाजित करता है।
PowerShell से टी चलाने के लिए /superuser/74127/tee-for-windows देखें
आप TextWriter वर्ग उपवर्ग सकता है, और उसके बाद का उपयोग कर Console.Out करने के लिए अपने उदाहरण आवंटित Console.SetOut पद्धति - जो विशेष रूप से लॉग विधि में दोनों विधियों में समान स्ट्रिंग को पारित करने के समान है।
एक और तरीका हो सकता है कि आप अपनी खुद की कंसोल क्लास घोषित करें और कक्षाओं के बीच अंतर करने के लिए स्टेटमेंट का उपयोग करें:
using Console = My.Very.Own.Little.Console;
मानक कंसोल तक पहुँचने के लिए आपको तब आवश्यकता होगी:
global::Console.Whatever
EDIT: यह विधि कंसोल सूचना को तीसरे पक्ष के पैकेज से आने वाली जानकारी को पुनर्निर्देशित करने की संभावना प्रदान करती है। राइटलाइन विधि को ओवरराइड करना मेरी स्थिति के लिए अच्छा है, लेकिन आपको अन्य लिखने के तरीकों को ओवरराइड करने की आवश्यकता हो सकती है यह तीसरे पक्ष के पैकेज पर निर्भर करता है।
पहले हमें StreamWriter से अंतर्निहित नई कक्षा बनाने की आवश्यकता है, जो CombinedWriter कहते हैं;
फिर Console.Out के साथ CombinedWriter का एक नया इंस्टेंट init;
अंत में हम Console.SetOut द्वारा नए वर्ग के तत्काल में कंसोल आउटपुट को रीडायरेक्ट कर सकते हैं;
निम्नलिखित कोड मेरे लिए नया वर्ग कार्य है।
public class CombinedWriter : StreamWriter
{
TextWriter console;
public CombinedWriter(string path, bool append, Encoding encoding, int bufferSize, TextWriter console)
:base(path, append, encoding, bufferSize)
{
this.console = console;
base.AutoFlush = true; // thanks for @konoplinovich reminding
}
public override void WriteLine(string value)
{
console.Write(value);
base.WriteLine(value);
}
}
public override void Write(char value);
, public override void Write(char[] buffer);
, public override void Write(string value);
और public override void Write(char[] buffer, int index, int count);
। अन्यथा यदि आप WriteLine(format, ...)
विधि का उपयोग करते हैं तो यह कंसोल पर प्रिंट नहीं करता है ।
Log4net आपके लिए यह कर सकता है। आप केवल कुछ इस तरह से लिखेंगे:
logger.info("Message");
एक कॉन्फ़िगरेशन यह निर्धारित करेगा कि प्रिंट आउट कंसोल, फ़ाइल या दोनों पर जाएगा।
मुझे लगता है कि जो आप पहले से उपयोग कर रहे हैं वह सबसे अच्छा तरीका है। अनिवार्य रूप से अपने आउटपुट को दर्पण करने की एक सरल विधि।
पहले शुरुआत में एक वैश्विक TextWriter घोषित करें:
private TextWriter txtMirror = new StreamWriter("mirror.txt");
फिर लिखने के लिए एक विधि बनाएं:
// Write empty line
private void Log()
{
Console.WriteLine();
txtMirror.WriteLine();
}
// Write text
private void Log(string strText)
{
Console.WriteLine(strText);
txtMirror.WriteLine(strText);
}
अब, उपयोग करने के बजाय Console.WriteLine("...");
, उपयोग करें Log("...");
। इतना ही आसान। यह और भी छोटा है!
यदि आप शापपत्र ( Console.SetCursorPosition(x, y);
) को स्थानांतरित करते हैं, तो कुछ परेशानी हो सकती है , लेकिन अन्यथा अच्छी तरह से काम करता है, मैं खुद भी इसका उपयोग करता हूं!
Console.Write();
यदि आप केवल WriteLines का उपयोग नहीं कर रहे हैं, तो उसी तरह से एक विधि बना सकते हैं
एक वर्ग का उपयोग करने का निर्णय, स्ट्रीमवृटर से विरासत में मिला, उपयोगकर्ता द्वारा सुझाव रखें सोच, काम करता है। लेकिन मुझे कंस्ट्रक्टर बेस में जोड़ना था।
{
this.console = console;
base.AutoFlush = true;
}
और विध्वंसक को एक स्पष्ट कॉल:
public new void Dispose ()
{
base.Dispose ();
}
अन्यथा, फ़ाइल सभी डेटा रिकॉर्ड करने से पहले बंद हो जाती है।
मैं इसका उपयोग कर रहा हूं:
CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out );
Console.SetOut (cw);
उत्कृष्ट समाधान के लिए सोच रखने के लिए धन्यवाद! मैंने कुछ और ओवरराइड जोड़े हैं ताकि कुछ कंसोल लिखने की घटनाओं से बचा जा सके, जो (मेरे उद्देश्यों के लिए) केवल कंसोल डिस्प्ले के लिए अपेक्षित हैं।
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RedirectOutput
{
public class CombinedWriter : StreamWriter
{
TextWriter console;
public CombinedWriter(string path, bool append, TextWriter consoleout)
: base(path, append)
{
this.console = consoleout;
base.AutoFlush = true;
}
public override void Write(string value)
{
console.Write(value);
//base.Write(value);//do not log writes without line ends as these are only for console display
}
public override void WriteLine()
{
console.WriteLine();
//base.WriteLine();//do not log empty writes as these are only for advancing console display
}
public override void WriteLine(string value)
{
console.WriteLine(value);
if (value != "")
{
base.WriteLine(value);
}
}
public new void Dispose()
{
base.Dispose();
}
}
class Program
{
static void Main(string[] args)
{
CombinedWriter cw = new CombinedWriter("combined.log", false, Console.Out);
Console.SetOut(cw);
Console.WriteLine("Line 1");
Console.WriteLine();
Console.WriteLine("Line 2");
Console.WriteLine("");
for (int i = 0; i < 10; i++)
{
Console.Write("Waiting " + i.ToString());
Console.CursorLeft = 0;
}
Console.WriteLine();
for (int i = 0; i < 10; i++)
{
Console.Write("Waiting " + i.ToString());
}
Console.WriteLine();
Console.WriteLine("Line 3");
cw.Dispose();
}
}
}
यदि आप किसी ऐसे कोड से कंसोल आउटपुट को डुप्लिकेट करते हैं जिसे आप नियंत्रित नहीं करते हैं, उदाहरण के लिए 3rd पार्टी लाइब्रेरी, TextWriter के सभी सदस्यों को ओवरराइट किया जाना चाहिए। कोड इस थ्रेड से विचारों का उपयोग करता है।
उपयोग:
using (StreamWriter writer = new StreamWriter(filePath))
{
using (new ConsoleMirroring(writer))
{
// code using console output
}
}
ConsoleMirroring वर्ग
public class ConsoleMirroring : TextWriter
{
private TextWriter _consoleOutput;
private TextWriter _consoleError;
private StreamWriter _streamWriter;
public ConsoleMirroring(StreamWriter streamWriter)
{
this._streamWriter = streamWriter;
_consoleOutput = Console.Out;
_consoleError = Console.Error;
Console.SetOut(this);
Console.SetError(this);
}
public override Encoding Encoding { get { return _consoleOutput.Encoding; } }
public override IFormatProvider FormatProvider { get { return _consoleOutput.FormatProvider; } }
public override string NewLine { get { return _consoleOutput.NewLine; } set { _consoleOutput.NewLine = value; } }
public override void Close()
{
_consoleOutput.Close();
_streamWriter.Close();
}
public override void Flush()
{
_consoleOutput.Flush();
_streamWriter.Flush();
}
public override void Write(double value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(string value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(object value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(decimal value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(float value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(bool value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(int value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(uint value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(ulong value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(long value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(char[] buffer)
{
_consoleOutput.Write(buffer);
_streamWriter.Write(buffer);
}
public override void Write(char value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(string format, params object[] arg)
{
_consoleOutput.Write(format, arg);
_streamWriter.Write(format, arg);
}
public override void Write(string format, object arg0)
{
_consoleOutput.Write(format, arg0);
_streamWriter.Write(format, arg0);
}
public override void Write(string format, object arg0, object arg1)
{
_consoleOutput.Write(format, arg0, arg1);
_streamWriter.Write(format, arg0, arg1);
}
public override void Write(char[] buffer, int index, int count)
{
_consoleOutput.Write(buffer, index, count);
_streamWriter.Write(buffer, index, count);
}
public override void Write(string format, object arg0, object arg1, object arg2)
{
_consoleOutput.Write(format, arg0, arg1, arg2);
_streamWriter.Write(format, arg0, arg1, arg2);
}
public override void WriteLine()
{
_consoleOutput.WriteLine();
_streamWriter.WriteLine();
}
public override void WriteLine(double value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(decimal value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(string value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(object value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(float value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(bool value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(uint value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(long value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(ulong value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(int value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(char[] buffer)
{
_consoleOutput.WriteLine(buffer);
_streamWriter.WriteLine(buffer);
}
public override void WriteLine(char value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(string format, params object[] arg)
{
_consoleOutput.WriteLine(format, arg);
_streamWriter.WriteLine(format, arg);
}
public override void WriteLine(string format, object arg0)
{
_consoleOutput.WriteLine(format, arg0);
_streamWriter.WriteLine(format, arg0);
}
public override void WriteLine(string format, object arg0, object arg1)
{
_consoleOutput.WriteLine(format, arg0, arg1);
_streamWriter.WriteLine(format, arg0, arg1);
}
public override void WriteLine(char[] buffer, int index, int count)
{
_consoleOutput.WriteLine(buffer, index, count);
_streamWriter.WriteLine(buffer, index, count);
}
public override void WriteLine(string format, object arg0, object arg1, object arg2)
{
_consoleOutput.WriteLine(format, arg0, arg1, arg2);
_streamWriter.WriteLine(format, arg0, arg1, arg2);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Console.SetOut(_consoleOutput);
Console.SetError(_consoleError);
}
}
}
वास्तव में आप TextWriter से विरासत में मिली अपनी कक्षा को लागू करके और WriteLine विधि को ओवरराइड करके ट्रेस करने के लिए Console.Out का एक पारदर्शी मिररिंग बना सकते हैं।
राइटलाइन में आप इसे ट्रेस में लिख सकते हैं जिसे तब फाइल में लिखने के लिए कॉन्फ़िगर किया जा सकता है।
मुझे यह उत्तर बहुत मददगार लगा: https://stackoverflow.com/a/10918320/379132
यह वास्तव में मेरे लिए काम किया!
मेरा जवाब सबसे अधिक गैर-स्वीकृत उत्तर पर आधारित है , और सबसे कम-मतदान जवाब भी है जो मुझे लगता है कि अब तक का सबसे सुरुचिपूर्ण समाधान है। यह उस धारा प्रकार के संदर्भ में थोड़ा अधिक सामान्य है जिसे आप उपयोग कर सकते हैं (आप MemoryStream
उदाहरण के लिए उपयोग कर सकते हैं ), लेकिन मैंने संक्षिप्तता के लिए बाद वाले उत्तर में शामिल सभी विस्तारित कार्यक्षमता को छोड़ दिया है ।
class ConsoleMirrorWriter : TextWriter
{
private readonly StreamWriter _writer;
private readonly TextWriter _consoleOut;
public ConsoleMirrorWriter(Stream stream)
{
_writer = new StreamWriter(stream);
_consoleOut = Console.Out;
Console.SetOut(this);
}
public override Encoding Encoding => _writer.Encoding;
public override void Flush()
{
_writer.Flush();
_consoleOut.Flush();
}
public override void Write(char value)
{
_writer.Write(value);
_consoleOut.Write(value);
}
protected override void Dispose(bool disposing)
{
if (!disposing) return;
_writer.Dispose();
Console.SetOut(_consoleOut);
}
}
उपयोग:
using (var stream = File.Create(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName)))
using (var writer = new ConsoleMirrorWriter(stream))
{
// Code using console output.
}