2009-10-27 3 views
8

En tant que discussed before, lorsqu'un BinaryReader ou un BinaryWriter est fermé, son Stream sous-jacent est également fermé (aargh). Considérez cette situation: une routine R est passée un MemoryStream, par exemple M; Je voudrais écrire quelques trucs à M et ensuite le passer à une autre routine pour plus de traitement (pas nécessairement d'écriture). Pour plus de commodité, je voudrais envelopper M dans un BinaryWriter pour écrire. Après l'écriture, j'en ai fini avec le BinaryWriter mais pas avec M.Comment puis-je "bifurquer" un flux dans .NET?

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(M)) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
} 

Mais, je ne peux pas disposer de la BinaryStream sans fermer M.

Q: Y a-t-il un moyen de faire l'une des choses suivantes?

  • extraire l'octet sous-jacent [] à partir d'un MemoryStream,
  • clone un flux
  • rouvre un flux après qu'il a été fermé
+0

Je ne connais pas C#, mais en Java, vous abandonneriez tout simplement sans fermer le BinaryWriter. La construction utilisant {...} ne ferme-t-elle pas? Alors n'utilisez pas cette construction! –

+0

P.S. Mais vous devez vous assurer de vider le BinaryWriter avant de l'abandonner. –

Répondre

2

Merci à plusieurs qui ont suggéré ToArray, j'ai été conduit à la bonne réponse, qui est `M.GetBuffer '. ToArray est pas trop mal, mais il

  • fait une copie
  • obtient seulement une partie de la mémoire tampon

GetBuffer saisit simplement une référence à l'octet sous-jacent [], qui est ce que je suis après.

+0

Ce qui a été souligné dans ma réponse ;) –

0

Une approche quelque peu naïve est d'utiliser

byte buf[] = MemoryStream.ToArray(); 

Pour copier le contenu du flux dans un tableau d'octets. Vous pouvez l'activer de nouveau dans un ruisseau avec

MemoryStream ms = new MemoryStream(buf); 
+0

À souligner: cette méthode fonctionne aussi bien en flux fermé qu'en live. –

2

Vous pouvez:

  • Appel M.ToArray() pour obtenir le flux comme un tableau d'octets.
  • BinaryWriter Schéma et remplacer la méthode Dispose pour empêcher la fermeture du flux d'enfant
+0

+1 spécifiquement pour le déroutement Dispose. –

+0

Ne pouvez-vous pas éviter d'appeler close/Dispose? –

-1

accoring à this M.Clone(); devrait marcher. Mais je peux me tromper ...

+0

-1 pour poster sur un site web qui ne permet pas de voir son contenu gratuitement, ce qui est plutôt inutile –

7

Vous devriez mieux obtenir l'octet sous-jacent [tampon] en utilisant

byte[] buffer = ms.GetBuffer(); 

Et puis copiez les données d'octets en utilisant la méthode Array.Copy(). Vous êtes libre de créer un nouveau flux avec celui-ci.

+0

Je ne comprends pas pourquoi vous dites qu'il vaut mieux utiliser GetBuffer et ensuite faire une copie en utilisant Array.Copy. Si je voulais une copie, j'utiliserais ToArray. –

+0

A partir de MSDN doc Cette méthode omet les octets inutilisés dans MemoryStream du tableau. Pour obtenir le tampon entier, utilisez la méthode GetBuffer. http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx –

+0

La "méthode" ci-dessus fait référence à MemoryStream.ToArray() –

5

Vous pouvez utiliser des choses comme le MiscUtil.IO.NonClosingStreamWrapper dans MiscUtil, qui enveloppe un Stream et ne tient pas compte simplement Close/Dispose demandes. Pour juste ce but.Juste pour l'ajouter ici

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(new NonClosingStreamWrapper(M))) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
}  
1

, une solution très simple serait pas à Dispose() l'écrivain.

void R(MemoryStream M) 
{ 
    B = new BinaryWriter(M); 

    // write some stuff using B   
    B.Flush(); 
    S(M); // now pass M to another routine for further processing 
} 

Maintenant, vous n'avez plus qu'à vous soucier de garder B dans la portée, ce qui sera le cas pendant R().

Ceci peut ne pas être la meilleure solution ici, mais il est intéressant de noter que les lecteurs et les rédacteurs n'ont pas besoin de se jeter.

+0

Espérons que 'BinaryWriter' ne mettra rien en mémoire tampon, alors ... –

+0

Mais assurez-vous d'avoir appelé B.flush() une fois que vous en aurez fini au cas où il n'aurait pas tout poussé vers M. (C'est ce qui serait nécessaire en Java, aucune idée sur C#) –

+0

OK, Adrian & Marc, j'ai oublié de Flush(). –

Questions connexes