Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以独占方式打开/修改XML文件?_C#_Xml - Fatal编程技术网

C# 以独占方式打开/修改XML文件?

C# 以独占方式打开/修改XML文件?,c#,xml,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);

我需要以独占方式打开一个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>


我知道我可以打开文件并使用文件方法逐行解析它,然后进行更改。。。但我希望有更优雅的东西。第一种方法——使用ReadXml加载文件——可以很好地修改文件,但它似乎没有任何以独占方式打开文件的选项。我遗漏了什么吗?

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

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);
}

在流中,如果替换文本比原始内容短,则需要将流头重置为文件开头,并删除现有内容以覆盖现有数据。请尝试将其置于ds.writeXml之前:

stream.Seek(0, SeekOrigin.Begin);
stream.SetLength(0);
第一行移动头部,第二行截断文件,因此,如果要替换的文本比原始文本短,则结尾处不会有多余的字符


请注意,正如Reed Copsey所指出的,最好先写,然后将长度设置为流的位置成员,因为如果替换文本的长度与替换文本的长度相同或更长,则这将无效,这可能会稍微更有效。

如果新的xml比旧的xml短,会发生什么情况?是否只需确保从文件的开头写入数据就可以了。i、 e.它将覆盖以前的数据,假设新数据大于或等于以前的数据?@Walt W:+1。我忘了打SetLength(…)电话了。在我编辑之后,它现在可以工作了。您需要在写入之前将长度设置为0,或者在写入之后将长度设置为位置。太棒了!我知道这一定是我错过的简单的东西@Walt W:您还可以在写入新数据后调用setlength,这可能会更有效(因为如果数据较长,则不会产生效果;如果数据较短,则只需重置长度一次,而不是在写入时…)