web-dev-qa-db-fra.com

Existe-t-il un moyen de fermer un StreamWriter sans fermer son BaseStream?

Mon problème racine est que lorsque using appelle Dispose sur un StreamWriter, il dispose également du BaseStream (même problème avec Close).

J'ai une solution pour cela, mais comme vous pouvez le voir, cela implique de copier le flux. Existe-t-il un moyen de le faire sans copier le flux?

Le but de ceci est d'obtenir le contenu d'une chaîne (initialement lue dans une base de données) dans un flux, afin que le flux puisse être lu par un composant tiers.
NB : Je ne peux pas changer le composant tiers.

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
    return baseCopy;
}

Utilisé comme

public void Noddy()
{
    System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
    My3rdPartyComponent.ReadFromStream(myStream);
}

Idéalement, je recherche une méthode imaginaire appelée BreakAssociationWithBaseStream, par exemple.

public System.IO.Stream CreateStream_Alternate(string value)
{
    var baseStream = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        writer.BreakAssociationWithBaseStream();
    }
    return baseStream;
}
104
Binary Worrier

Si vous utilisez .NET Framework 4.5 ou version ultérieure, il existe une surcharge StreamWriter à l'aide de laquelle vous pouvez demander que le flux de base reste ouvert lorsque le programme d'écriture est fermé .

Dans les versions antérieures de .NET Framework antérieures à 4.5, StreamWriter suppose qu'il possède le flux. Options:

  • Ne jetez pas le StreamWriter; rincez-le.
  • Créez un wrapper de flux qui ignore les appels à Close/Dispose mais procède à tout le reste par procuration. J'ai une implémentation de cela dans MiscUtil , si vous voulez l'attraper à partir de là.
106
Jon Skeet

.NET 4.5 a une nouvelle méthode pour ça!

http://msdn.Microsoft.com/EN-US/library/gg712853 (v = VS.110, d = hv.2) .aspx

public StreamWriter(
    Stream stream,
    Encoding encoding,
    int bufferSize,
    bool leaveOpen
)
41
maliger

N'appelez simplement pas Dispose sur le StreamWriter. La raison pour laquelle cette classe est jetable n'est pas parce qu'elle contient des ressources non gérées, mais pour permettre l'élimination du flux qui lui-même pourrait contenir des ressources non gérées. Si la durée de vie du flux sous-jacent est gérée ailleurs, pas besoin de disposer du rédacteur.

32
Darin Dimitrov

Le flux de mémoire a une propriété ToArray qui peut être utilisée même lorsque le flux est fermé. To Array écrit le contenu du flux dans un tableau d'octets, quelle que soit la propriété Position. Vous pouvez créer un nouveau flux en fonction du flux dans lequel vous avez écrit.

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
    return returnStream;
}
5
Tudor

Vous devez créer un descendant de StreamWriter et remplacer sa méthode d'élimination, en passant toujours false au paramètre de suppression, cela forcera l'écrivain de flux à ne pas se fermer, le StreamWriter appelle simplement dispose dans la méthode close, il n'est donc pas nécessaire de le remplacer (bien sûr, vous pouvez ajouter tous les constructeurs si vous le souhaitez, je n'en ai qu'un):

public class NoCloseStreamWriter : StreamWriter
{
    public NoCloseStreamWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(false);
    }
}
1
Aaron Murgatroyd