Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the XMLWriter Not Closing?

I am having some trouble with the XMLWriter not closing. I can successfully write the XML file once but if I try to write it again (overwrite) I get the exception:

"The process cannot access the file 'somefile.xml' because it is being used by another process."

    Dim settings = New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = " "
    settings.NewLineOnAttributes = True

    Try
    Dim writer As XmlWriter = XmlWriter.Create(System.IO.File.Create("somefile.xml"))
        writer.WriteStartDocument(True)
        writer.WriteStartElement("root")
        For rowCounter As Integer = ds.Tables(0).Rows.Count - 1 To 0 Step -1
            writer.WriteStartElement("someelement")
            writer.WriteElementString("col0", ds.Tables(0).Rows(rowCounter)(0).ToString)
            writer.WriteElementString("col1", ds.Tables(0).Rows(rowCounter)(1).ToString)
            writer.WriteElementString("col2", ds.Tables(0).Rows(rowCounter)(2).ToString)
            writer.WriteElementString("col3", ds.Tables(0).Rows(rowCounter)(3).ToString)
            writer.WriteElementString("col4", ds.Tables(0).Rows(rowCounter)(4).ToString)
            writer.WriteElementString("col5", ds.Tables(0).Rows(rowCounter)(5).ToString)
            writer.WriteElementString("col6", ds.Tables(0).Rows(rowCounter)(6).ToString)
            writer.WriteElementString("col7", ds.Tables(0).Rows(rowCounter)(7).ToString)
            writer.WriteEndElement()
        Next
        writer.WriteEndElement()
        writer.WriteEndDocument()
    Catch ex As System.IO.IOException
        MessageBox.Show(ex.Message)
    Finally
        writer.Flush()
        writer.Close()
    End Try
like image 370
Error1f1f Avatar asked Mar 05 '11 18:03

Error1f1f


1 Answers

What you are missing, is XmlWriterSettings. You declare it, but you don't use it, and when you don't set CloseOutput by hand, the default is false, which means that the output is not closed (in this case your filestream).

To have it behave the way you want it, change your code like this:

Dim settings = New XmlWriterSettings()
settings.Indent = True
settings.IndentChars = " "
settings.NewLineOnAttributes = True
settings.CloseOutput = True             ' <<<< the change '

Using writer As XmlWriter = XmlWriter.Create(System.IO.File.Create("somefile.xml"), settings)
    '.... etc'
End Using

In case you're wondering about how this really works internally, here's the Close method of XmlEncodedRawTextWriterIndent, the internal XmlWriter used in your scenario.

// courtesy of Red Gate's Reflector
public override void Close()
{
    this.FlushBuffer();
    this.FlushEncoder();
    this.writeToNull = true;
    if (this.stream != null)
    {
        this.stream.Flush();
        if (this.closeOutput)      //this flag is set to settings.CloseOutput
        {
            this.stream.Close();
        }
        this.stream = null;
    }
    else if (this.writer != null)
    {
        this.writer.Flush();
        if (this.closeOutput)
        {
            this.writer.Close();
        }
        this.writer = null;
    }
}
like image 171
Abel Avatar answered Sep 28 '22 02:09

Abel