Christoffer Soop
Christoffer Soop

Reputation: 1508

How do I replace the contents of an existing XML file in C#.NET?

When trying to replace the content of an XML file in C#.NET with a snippet like this:

string file = Path.GetTempFileName(); // pretend this is a real file
string tmpFile = Path.GetTempFileName();

using (var writer = XmlWriter.Create(File.Create(tmpFile)))
{
    writer.WriteStartElement("root");
    for (int i = 0; i < 100; i++)
    {
        writer.WriteElementString("test", null, 
            "All work and no play makes Jack a dull boy");
    }
    writer.WriteEndElement();
}

File.Delete(file);
File.Move(tmpFile, file);

... I get a System.IO.IOException claiming that the file is already opened by another process.

Upvotes: 1

Views: 1028

Answers (2)

Christoffer Soop
Christoffer Soop

Reputation: 1508

For some reason the XmlWriter class evidently does not dispose the underlying stream for the temporary file. Putting the stream in a "using" clause of its own makes sure the stream is closed correctly. Changing the code to

string file = Path.GetTempFileName(); // pretend this is a real file
string tmpFile = Path.GetTempFileName();

using (var stream = File.Create(tmpFile))
using (var writer = XmlWriter.Create(stream))
{
    writer.WriteStartElement("root");
    for (int i = 0; i < 100; i++)
    {
        writer.WriteElementString("test", null, 
            "All work and no play makes Jack a dull boy");
    }
    writer.WriteEndElement();
}                
File.Delete(file);
File.Move(tmpFile,file);

... makes the IOException disappear and it works as intended.

Upvotes: 6

Greg D
Greg D

Reputation: 44076

Using statements can be chained. Slightly modifying your code:

string file = Path.GetTempFileName(); // pretend this is a real file
string tmpFile = Path.GetTempFileName();

using (var stream = File.Create(tmpFile))
using (var writer = XmlWriter.Create(stream))
{
    writer.WriteStartElement("root");
    for (int i = 0; i < 100; i++)
    {
        writer.WriteElementString("test", null, 
            "All work and no play makes Jack a dull boy");
    }
    writer.WriteEndElement();
}                
File.Delete(file);
File.Move(tmpFile,file);

If you're dealing with multiple disposable entities over the same scope (not an uncommon occurrence), this avoids nastily deep nesting. :)

Upvotes: 4

Related Questions