web-dev-qa-db-fra.com

Pouvez-vous empêcher un StreamReader de disposer du flux sous-jacent?

Y a-t-il un moyen de faire cela:

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sr = new StreamReader(this.logFile))
{
    // Read the data in
}

// ... later on in the class ...

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sw = new StreamWriter(this.logFile))
{
    // Write additional data out...
}

Sans avoir à ouvrir le fichier deux fois?

Je n'arrive pas à faire en sorte que le StreamReader ne dispose pas de mon flux. Je ne veux pas simplement laisser cela sortir de son champ d'application non plus. Ensuite, le ramasse-miettes appellera éventuellement Dispose, tuant le flux.

44
John Gietzen

Je ne veux pas simplement laisser cela sortir de son champ d'application non plus. Ensuite, le ramasse-miettes appellera éventuellement Dispose, tuant le flux.

Garbage Collector appellera la méthode Finalize (destructeur), et non la méthode Dispose. Le finaliseur appellera Dispose(false) qui non éliminera le flux sous-jacent. Vous devriez être OK en laissant le StreamReader sortir du champ d'application si vous devez utiliser directement le flux sous-jacent. Assurez-vous simplement de disposer manuellement du flux sous-jacent lorsque cela convient.

44
Mehrdad Afshari

.NET 4.5 résoudra finalement ce problème avec de nouveaux constructeurs sur StreamReader et StreamWriter qui prennent un paramètre leaveOpen:

StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen)

StreamWriter(Stream stream, System.Text.Encoding encoding, int bufferSize, bool leaveOpen)
64
Simon Buchan

Vous pouvez utiliser la classe NonClosingStreamWrapper de la bibliothèque MiscUtil de Jon Skeet , elle sert exactement à cela.

15
Thomas Levesque

Vous pouvez créer une nouvelle classe qui hérite de StreamReader et remplacer la méthode Close. Dans votre méthode Close, appelez Dispose (false), ce qui, comme Mehrdad l'a fait remarquer, ne ferme pas le flux. La même chose s'applique à StreamWriter, bien sûr.

Cependant, il semble qu'une meilleure solution consisterait simplement à conserver les instances StreamReader et StreamWriter aussi longtemps que vous en aurez besoin. Si vous envisagez déjà de garder le flux ouvert, gardez également un StreamReader et un StreamWriter ouverts. Si vous utilisez correctement StreamWriter.Flush et Stream.Seek, vous devriez pouvoir le faire, même en lecture et en écriture.

3
Aaron

Il suffit de retirer le using-Block. Je pense que vous n'avez pas besoin de Dispose () le StreamReader si vous ne voulez pas faire Dispose () du flux.

2
eWolf

Utilisez une autre surcharge de constructeur où vous pouvez spécifier un paramètre "leaveOpen" sur "true"

2
HANiS

Fermez-le vous-même dans une clause try/finally lorsque vous avez terminé.

var sr = new StreamReader();
try {
    //...code that uses sr
    //....etc
}
finally
{
    sr.Close();
}
0
Mike Atlas

J'utilise toujours quelque chose comme ceci: (il utilise également l'argument leaveOpen)

public static class StreamreaderExtensions
{
    public static StreamReader WrapInNonClosingStreamReader(this Stream file) => new StreamReader(file, Encoding.UTF8, true, 1024, true);
}

Usage:

using (var reader = file.WrapInNonClosingStreamReader())
{
     ....
}
0
Nick N.