136 votes

Est-il possible de fermer un StreamWriter sans fermer BaseStream?

Mon problème de base est que, lorsque l' using des appels Dispose sur StreamWriter, il dispose également de la BaseStream (même problème avec Close).

J'ai une solution pour cela, mais comme vous pouvez le voir, il implique de copier le flux. Est-il possible de faire cela sans avoir à copier le flux?

Le but de cette opération est d'obtenir le contenu d'une chaîne de caractères (à l'origine de lire à partir d'une base de données) dans un cours d'eau, de sorte que le flux peut être lu par un tiers de la composante.
NB je ne peux pas changer les composants 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 suis à la recherche d'un imaginaire méthode 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;
}

139voto

Jon Skeet Points 692016

Si vous êtes en utilisant .NET Framework 4.5 ou une version ultérieure, il est un StreamWriter surcharge à l'aide duquel vous pouvez demander le flux de base pour être ouvert lorsque l'écrivain est fermé.

Dans les versions antérieures de .NET Framework avant à 4.5 StreamWriter suppose qu'il détient les flux. Options:

  • Ne jetez pas l' StreamWriter; il suffit de le rincer.
  • Créer un gestionnaire de flux qui permet d'ignorer les appels à l' Close/Dispose , mais les procurations tout le reste. J'ai une mise en œuvre que dans MiscUtil, si vous voulez prendre à partir de là.

50voto

maliger Points 331

.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
)
 

37voto

Darin Dimitrov Points 528142

N'appelez tout 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 pourrait contenir des ressources non gérées. Si la vie du flux sous-jacent est gérée ailleurs, inutile de disposer du rédacteur.

8voto

Tudor Points 21

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 que 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;
}
 

2voto

Aaron Murgatroyd Points 857

Vous devez créer un descendant de StreamWriter et redéfinir sa méthode de disposition, en transmettant toujours false au paramètre de mise au rebut, cela force le rédacteur de flux à ne PAS fermer, le StreamWriter appelle simplement la méthode de la méthode de fermeture. remplacez-le (bien sûr, vous pouvez ajouter tous les constructeurs si vous voulez, 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);
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X