独家打开/修改XML文件?

时间:2009-09-01 17:15:38

标签: c# xml

我需要专门打开一个XML文件,进行修改并保存。

我可以打开它并很容易地进行修改:

DataSet ds = new DataSet();
ds.ReadXml(filename);

DataTable table = ds.Tables[0];
DataRow[] rows = table.Select("Inventory== 1");
DataRow row = rows[0];
row["Inventory"] = "2";
ds.WriteXml(filename);

一切都很好,但它不会锁定文件。我绝对需要锁定文件。

所以我尝试了一个流:

FileStream stream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);

DataSet ds = new DataSet();
ds.ReadXml(stream);

DataTable table = ds.Tables[0];
DataRow[] rows = table.Select("Inventory== 1");
DataRow row = rows[0];
row["Inventory"] = "2";
ds.WriteXml(stream);
stream.Close();

它以独占方式打开文件,但是当它保存时,它会将XML附加到时间结束,它不会覆盖它,所以我最终会得到类似的结果:

<Widgets>
  <Widget Code="5" Number="10" Inventory="1" />
  <Widget Code="6" Number="11" Inventory="15" />
  <Widget Code="7" Number="12" Inventory="22" />
</Widgets>
<Widgets>
   <Widget Code="5" Number="10" Inventory="2" />
  <Widget Code="6" Number="11" Inventory="15" />
  <Widget Code="7" Number="12" Inventory="22" />
</Widgets>

我想要的是:

<Widgets>
  <Widget Code="5" Number="10" Inventory="2" />
  <Widget Code="6" Number="11" Inventory="15" />
  <Widget Code="7" Number="12" Inventory="22" />
</Widgets>

我知道我可以打开文件并使用File方法逐行解析它并进行更改......但我希望有更优雅的东西。第一种方法 - 使用ReadXml加载文件 - 文件修改就好了,但似乎没有任何选项可以专门打开文件。我错过了什么吗?

2 个答案:

答案 0 :(得分:6)

您可以使用流来完成,但是您需要在撰写之前重置

using(FileStream stream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
    DataSet ds = new DataSet();
    ds.ReadXml(stream);

    DataTable table = ds.Tables[0];
    DataRow[] rows = table.Select("Inventory== 1");
    DataRow row = rows[0];
    row["Inventory"] = "2";

    // Reset the stream here to the beginning of the file!
    stream.Seek(0, SeekOrigin.Begin);
    ds.WriteXml(stream);
    // Reset the length of the stream prior to closing it, in case it's shorter than it used to be...
    stream.SetLength(stream.Position);
}

答案 1 :(得分:5)

在您的信息流中,您需要将信息流的头部重置为文件的开头并删除现有内容以覆盖现有数据,以防替换文本短于原始内容。尝试在ds.writeXml:

之前放置它
stream.Seek(0, SeekOrigin.Begin);
stream.SetLength(0);

第一行移动头部,第二行截断文件,因此如果要替换文本的内容比原始文本短,则最后不会有无关的字符。

请注意,正如Reed Copsey所指出的那样,最好先进行写入,然后将长度设置为流的Position成员,因为如果替换文本的长度相同,则无效比替换的文本更长,这可能会稍微提高效率。