简体   繁体   中英

How can I set StreamWriter's source as multiple in .NET?

I am developing some network program in .NET. I want to see entire text stream on my output window as log. So I tried to search the solution for setting mutiple source on StreamWriter. But I can not find that. I want these style like below not extension method :

var sw = new StreamWriter(socketStream, traceStream)

or

var sw = new StreamWriter(socketStream);
sw.setSecondStream(traceStream);

It shouldn't be so hard to make a stream splitter. For a Write-only stream without Seek functions it's pretty simple.

The constructor call would then look like

var sw = new StreamWriter(new WriteStreamSplitter(socketStream, traceStream));

and the class (untested, just a mock up)

class WriteStreamSplitter : Stream
{
    public WriteStreamSplitter(Stream a, Stream b)
    {
        _streamA = a;
        _streamB = b;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        _streamA.Write(buffer, offset, count);
        _streamB.Write(buffer, offset, count);
    }

    public override bool CanWrite { get { return true; } }
    public override bool CanRead  { get { return false; } }

    // trivial overloads of all other abstract members, 
    // they are allowed to throw NotImplemented


    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            // Maybe it's best to do nothing here but a StreamWriter 
            // assumes 'ownership' of the wrapped stream, 
            // so if we want to continue that pattern:

            // the guidelines say these shouldn't throw
            _streamA.Dispose();
            _streamB.Dispose();
        }
    }
}

I think you should take a different approach. Create a class and aggregate a StreamWriter. Then use MyStreamWriter to write to the stream instead of directly use a StreamWriter:

class MyStreamWriter
{
   private StreamWriter sw;

   // Constructor
   public MyStreamWriter(Stream socketStream)
   {
      sw = new StreamWriter(socketStream);
   }

   // Example function
   public void WriteLine(string myText)
   {
     Trace.WriteLine(myText);
     sw.WriteLine(myText);
   }
}

This allows you to attach additional functionality.

Instead of using your code to create an instance of the StreamWriter you would simply create a MyStreamWriter :

var sw = new MyStreamWriter(socketStream);

I use the Trace class to log the message instead of writing it to another stream. Components like log4net allow to log all calls to the Trace (or Debug) class and route it to a log-file / SQL-Server / whatever. This way you would have a much more flexible solution.

As a alternative you could implement a TraceListener by yourself which could simply add all of your output to a TextBox.

Thank you, Henk. Good Idea!

But I change a little. I need just log fuctionality, so I added log concept. It based on your splitter idea.

loggable stream classs

public class LoggableStream : Stream
{
    private Stream _stream;
    private Encoding _textEncoding;



    public LoggableStream(Stream stream, Encoding textEncoding)
    {
        _stream = stream;
        _textEncoding = textEncoding;
    }

    public override bool CanRead
    {
        get
        {
            return _stream.CanRead;
        }
    }

    public override bool CanSeek
    {
        get
        {
            return _stream.CanSeek;
        }
    }

    public override bool CanWrite
    {
        get
        {
            return _stream.CanWrite;
        }
    }

    public override long Length
    {
        get
        {
            return _stream.Length;
        }
    }

    public override long Position
    {
        get
        {
            return _stream.Position;
        }
        set
        {
            _stream.Position = Position;
        }
    }

    public override void Flush()
    {
        _stream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        var result = _stream.Read(buffer, offset, count);

        try
        {
            var log = this._textEncoding.GetString(buffer, offset, count);
            Trace.TraceInformation("READ : " + log);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        return result;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        var result = _stream.Seek(offset, origin);
        return result;
    }

    public override void SetLength(long value)
    {
        _stream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        _stream.Write(buffer, offset, count);

        try
        {
            var log = this._textEncoding.GetString(buffer, offset, count);
            Trace.TraceInformation("WRIT : " + log);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }
    }
}

usage

using (var netStream = _controlClient.GetStream())
using (var sr = new StreamReader(new LoggableStream(netStream, Encoding.UTF8)))
using (var sw = new StreamWriter(new LoggableStream(netStream, Encoding.UTF8)))
{
    var readLine = sr.ReadLine();
    sw.WriteLine("hello");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM