2015-11-26 1 views
2

Je développe un programme réseau dans .NET. Je veux voir le flux de texte entier sur ma fenêtre de sortie en tant que journal. J'ai donc essayé de rechercher la solution pour définir la source mutiple sur StreamWriter. Mais je ne peux pas trouver ça. Je veux que ces style comme ci-dessous ne méthode d'extension:Comment définir la source de StreamWriter comme multiple dans .NET?

var sw = new StreamWriter(socketStream, traceStream) 

ou

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

connexes, mais pas de réponse concrète [ici] (http://stackoverflow.com/questions/1055872/) –

+0

Il me semble que vous cherchez un Tee Stream. Attention: un tel arrangement pourrait avoir des besoins de mémoire illimités (si un flux écrit plus vite que l'autre). Voici une implémentation qui bloque plutôt que des tampons: http://www.cookcomputing.com/blog/archives/tee-stream-in-csharp – spender

Répondre

2

Il ne devrait pas être si difficile de faire un séparateur de flux. Pour un flux en écriture seule sans fonctions Seek, c'est plutôt simple.

L'appel constructeur serait alors ressembler à

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

et la classe (non testé, juste une maquette)

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

Rappelez-vous ... Une armée marche aussi vite que son plus lent soldat ... – spender

+1

Oui, mais il n'y a pas de frais généraux de stockage ici et l'écriture bloquera juste. –

2

Je pense que vous devriez adopter une approche différente. Créez une classe et agrègez un StreamWriter. Utilisez ensuite MyStreamWriter pour écrire dans le flux au lieu d'utiliser directement un 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); 
    } 
} 

Cela vous permet d'attacher des fonctionnalités supplémentaires.

Au lieu d'utiliser votre code pour créer une instance de la StreamWriter vous suffit de créer un MyStreamWriter:

var sw = new MyStreamWriter(socketStream); 

J'utilise la classe Trace pour enregistrer le message au lieu d'écrire à un autre cours d'eau. Des composants tels que log4net permettent de consigner tous les appels à la classe Trace (ou Debug) et de l'acheminer vers un fichier journal/SQL-Server/any. De cette façon, vous auriez une solution beaucoup plus flexible. Comme alternative, vous pouvez implémenter un TraceListener par vous-même qui pourrait simplement ajouter toute votre sortie à un TextBox.

0

Merci, Henk. Bonne idée!

Mais je change un peu. J'ai juste besoin de connecter la fonctionnalité, donc j'ai ajouté le concept de journal. C'est basé sur votre idée de séparateur.

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

utilisation

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