Mein Grundproblem ist, dass beim using
Aufruf Dispose
von a StreamWriter
auch das BaseStream
(gleiche Problem mit Close
) beseitigt wird .
Ich habe eine Problemumgehung dafür, aber wie Sie sehen können, muss der Stream kopiert werden. Gibt es eine Möglichkeit, dies zu tun, ohne den Stream zu kopieren?
Der Zweck hierbei besteht darin, den Inhalt einer Zeichenfolge (ursprünglich aus einer Datenbank gelesen) in einen Stream zu übertragen, damit der Stream von einer Komponente eines Drittanbieters gelesen werden kann.
NB : Ich kann die Komponente eines Drittanbieters nicht ändern.
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;
}
Benutzt als
public void Noddy()
{
System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
My3rdPartyComponent.ReadFromStream(myStream);
}
Idealerweise suche ich nach einer imaginären Methode namens BreakAssociationWithBaseStream
z
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;
}
Antworten:
Wenn Sie .NET Framework 4.5 oder höher verwenden, gibt es eine StreamWriter-Überladung, mit der Sie den Basis-Stream auffordern können, beim Schließen des Writers offen zu bleiben .
In früheren Versionen von .NET Framework vor 4.5 wird
StreamWriter
davon ausgegangen, dass es den Stream besitzt. Optionen:StreamWriter
; spülen Sie es einfach.Close
/ ignoriert,Dispose
aber alles andere weiterleitet. Ich habe eine Implementierung davon in MiscUtil , wenn Sie es von dort abrufen möchten.quelle
leaveOpen
Parameter festzulegen, nachdem erStreamWriter
erstellt wurde?Dispose
. Das Methodenende macht das nicht automatisch. Es kann später finalisiert werden, wenn es einen Finalizer hat, aber das ist nicht dasselbe - und es ist immer noch nicht klar, welche Gefahr Sie erwarten. Wenn Sie der Meinung sind, dass es unsicher ist,StreamWriter
eine Methode zurückzugeben, weil sie vom GC automatisch entsorgt werden könnte, stimmt das einfach nicht.StreamWriter
hat keinen Finalizer - genau aus diesem Grund würde ich das nicht erwarten..NET 4.5 hat dafür eine neue Methode!
http://msdn.microsoft.com/EN-US/library/gg712853(v=VS.110,d=hv.2).aspx
quelle
bufferSize
ist1024
. Details finden Sie hier .Rufen Sie einfach nicht
Dispose
anStreamWriter
. Der Grund, warum diese Klasse verfügbar ist, liegt nicht darin, dass sie nicht verwaltete Ressourcen enthält, sondern darin, den Stream zu entsorgen, der selbst nicht verwaltete Ressourcen enthalten könnte. Wenn die Lebensdauer des zugrunde liegenden Streams an anderer Stelle behandelt wird, muss der Writer nicht entsorgt werden.quelle
Flush
den Job nicht erledigen, falls er Daten puffert?Der Speicherstrom verfügt über eine ToArray-Eigenschaft, die auch bei geschlossenem Strom verwendet werden kann. To Array schreibt den Stream-Inhalt unabhängig von der Position-Eigenschaft in ein Byte-Array. Sie können einen neuen Stream basierend auf dem Stream erstellen, in den Sie geschrieben haben.
quelle
Stream.Position
kann nicht aufgerufen werden, nachdem es entsorgt wurde.Sie müssen einen Nachkommen des StreamWriter erstellen und dessen Dispose-Methode überschreiben. Indem Sie immer false an den Disposing-Parameter übergeben, wird der Stream-Writer gezwungen, NICHT zu schließen. Der StreamWriter ruft nur Dispose in der Close-Methode auf, sodass dies nicht erforderlich ist überschreibe es (natürlich kannst du alle Konstruktoren hinzufügen, wenn du willst, ich habe nur einen):
quelle
disposing
Flagge ist ein Teil desIDisposable
Musters . Wenn Sie immerfalse
an dieDispose(bool)
Methode der Basisklasse übergeben, signalisiert dies im Wesentlichen,StreamWriter
dass sie vom Finalizer aufgerufen wird (was beimDispose()
expliziten Aufruf nicht der Fall ist ) und daher nicht auf verwaltete Objekte zugreifen sollte. Aus diesem Grund wird der Basisstrom nicht entsorgt. Die Art und Weise, wie Sie dies erreicht haben, ist jedoch ein Hack. es wäre viel einfacher, einfach gar nicht erst anzurufenDispose
!OwnedStream
, die ignoriertDispose(bool)
undClose
).