2012-03-23 6 views
6

Così sto usando la filestream all'interno xmlreaderPerché filestream non chiusa da XmlReader

using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), readerSettings)) 
{ 
    reader.close() 
} 

Tuttavia, il feed file nel XmlReader ancora in stato di blocco dopo l'utilizzo dell'ambito, strano, ho thougt il xmlreader sta andando per chiudere il filestream per me, non è vero?

Grazie per l'aiuto.

risposta

7

Hai provato questo?

using(var stream = new FileStream(archivePath, FileMode.Open)) 
using(var reader = XmlReader.Create(stream, readerSettings)) 
{ 

} 

io non ho trovato nulla nella documentazione esplicitamente dichiarato che il XmlReader chiamerebbero smaltire il flusso sottostante quando è stato smaltito. Inoltre, lo uso sempre come mostrato sopra e non ho mai riscontrato un problema.

Navigando attraverso il riflettore Non trovo nemmeno casi in cui si chiami Dispose() sullo streaming quando si crea un XmlTextReaderImpl. Il XmlTextReaderImpl non implementa Dispose() e il suo metodo Close() assomiglia a questo:

internal void Close(bool closeInput) 
{ 
    if (this.parsingFunction != ParsingFunction.ReaderClosed) 
    { 
     while (this.InEntity) 
     { 
      this.PopParsingState(); 
     } 
     this.ps.Close(closeInput); 
     this.curNode = NodeData.None; 
     this.parsingFunction = ParsingFunction.ReaderClosed; 
     this.reportedEncoding = null; 
     this.reportedBaseUri = string.Empty; 
     this.readState = ReadState.Closed; 
     this.fullAttrCleanup = false; 
     this.ResetAttributes(); 
    } 
} 
+1

a dire il vero, no. Ho pensato che XmlReader è come StreamReader, chiuderà il flusso interno una volta fatto. usare due istruzioni usando è solo un po 'maldestro. –

+1

Aneddot, ma la maggior parte degli esempi che vedo usano i due 'using'. –

+1

@TOMMYWANG: Beh, si potrebbe pensare così, ma non riesco a trovare da nessuna parte nel codice (usando reflector) dove 'XmlTextReaderImpl' (che è ciò che' XmlReader.Create() 'restituisce effettivamente) elimina lo stream. Se chiudesse lo stream si verificherebbero problemi quando si usa un flusso per più lettori (cosa succede se voglio mantenere vivo il flusso? Perché il lettore dovrebbe decidere che non posso?), Quindi richiede l'approccio sicuro del fare Niente. Non sono d'accordo che è "goffo", ma "goffo" è meglio di "rotto" –

1

Si avrebbe bisogno di tenere traccia del FileStream e XmlReader. È potenzialmente pericoloso per XmlReader chiudere il flusso sottostante. Nel caso in cui lo FileStream sia utilizzato da più lettori: se uno di questi lettori dovesse chiudere il flusso ciò causerebbe il fallimento imprevisto degli altri lettori.

È un po 'un problema dal momento che alcuni lettori e autori di stream chiuderanno il flusso sottostante, mentre altri no. Come best practice, chiudo sempre e getta i flussi che apro manualmente. Ciò aiuta anche a mitigare alcuni "trucchi" con determinati flussi.
ad es. You need to dispose a GZipStream before calling .ToArray()

9

Dovresti essere in grado di controllarlo tramite XmlReaderSettings.CloseInput.

readerSettings.CloseInput = true; 
using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), readerSettings)) 
{ 
    // do work with the reader 
} 

Oppure, in modo più conciso se non si cura di altre impostazioni del lettore:

using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), new XmlReaderSettings() { CloseInput = true })) 
{ 
    // do work with the reader 
} 
+1

Buona risposta, questo impedisce a FxCop di lamentarsi di più cessioni se tu set CloseInput = false, che mi dava fastidio. – briantyler

+0

Non è l'istruzione reader.close() qui ridondante da quando si esce dall'istruzione using chiamerà Dispose() e che chiama Close()? – Kent

0

Pochi anni di ritardo, ma forse questo potrebbe aiutare qualcuno ...

ho provato il metodo di Eric come sembrava una buona soluzione, ma ho continuato a ricevere l'avviso CA2202 quando eseguivo l'analisi del codice VS su di esso.

Nella parte inferiore della CA2202, Microsoft consiglia di utilizzare il seguente: (. Ho leggermente modificato il per "XmlReader")

Stream stream = null; 
try 
{ 
    stream = new FileStream("file.txt", FileMode.Open); 
    using (XmlReader reader = new XmlReader (stream)) 
    { 
     stream = null; 
     // Use the reader object... 
    } 
} 
finally 
{ 
    if(stream != null) 
     stream.Dispose(); 
} 

invece di ...

using (Stream stream = new FileStream("file.txt", FileMode.Open)) 
{ 
    using (XmlReader reader = new XmlReader (stream)) 
    { 
     // Use the reader object... 
    } 
} 

È molto più lungo ma almeno non lancia alcun avviso.