独家打开/修改XML文件?

BDW*_*BDW 3 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);
Run Code Online (Sandbox Code Playgroud)

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

所以我尝试了一个流:

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();
Run Code Online (Sandbox Code Playgroud)

这会以独占方式打开文件,但是当它保存时,它会将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>
Run Code Online (Sandbox Code Playgroud)

我想要的是:

<Widgets>
  <Widget Code="5" Number="10" Inventory="2" />
  <Widget Code="6" Number="11" Inventory="15" />
  <Widget Code="7" Number="12" Inventory="22" />
</Widgets>
Run Code Online (Sandbox Code Playgroud)

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

Ree*_*sey 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);
}
Run Code Online (Sandbox Code Playgroud)


Wal*_*t W 5

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

stream.Seek(0, SeekOrigin.Begin);
stream.SetLength(0);
Run Code Online (Sandbox Code Playgroud)

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

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