【问题标题】:How can I set StreamWriter's source as multiple in .NET?如何在 .NET 中将 StreamWriter 的源设置为多个?
【发布时间】:2016-02-29 08:36:44
【问题描述】:

我正在.NET 中开发一些网络程序。 我想在我的输出窗口上看到整个文本流作为日志。 所以我尝试搜索在 StreamWriter 上设置多个源的解决方案。 但我找不到那个。 我想要下面的这些样式而不是扩展方法:

var sw = new StreamWriter(socketStream, traceStream)

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

【问题讨论】:

  • 相关,但没有具体答案here
  • 在我看来,您正在寻找 Tee Stream。警告:这样的安排可能有无限的内存需求(如果一个流的写入速度比另一个快)。这是一个阻塞而不是缓冲区的实现:cookcomputing.com/blog/archives/tee-stream-in-csharp

标签: c# .net sockets logging streamwriter


【解决方案1】:

制作分流器应该不难。对于没有 Seek 函数的只写流,它非常简单。

构造函数调用看起来像

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

和班级(未经测试,只是一个模型)

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

【讨论】:

  • 是的,但是这里没有存储开销,写入只会阻塞。
【解决方案2】:

我认为你应该采取不同的方法。创建一个类并聚合一个 StreamWriter。然后使用 MyStreamWriter 写入流,而不是直接使用 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);
   }
}

这允许您附加其他功能。

您只需创建一个 MyStreamWriter,而不是使用您的代码创建 StreamWriter 的实例:

var sw = new MyStreamWriter(socketStream);

我使用 Trace 类来记录消息,而不是将其写入另一个流。 log4net 之类的组件允许记录对 Trace(或 Debug)类的所有调用,并将其路由到日志文件/SQL-Server/其他。这样,您将获得更灵活的解决方案。

作为替代方案,您可以自己实现 TraceListener,它可以简单地将所有输出添加到 TextBox。

【讨论】:

    【解决方案3】:

    谢谢你,亨克。好主意!

    但我改变了一点。我只需要日志功能,所以我添加了日志概念。它基于您的拆分器想法。

    可记录的流类

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

    用法

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

    【讨论】:

      猜你喜欢
      • 2017-09-17
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2019-12-29
      • 2020-10-15
      • 2018-12-28
      • 2012-04-18
      • 2016-03-31
      相关资源
      最近更新 更多