XDocument.Save() 某物块文件
XDocument.Save() something blocks file
我打算使用 XDocument.Load() 加载一个 xml 文件,更新一些元素的值,然后使用 XDocument.Save() 保存它。读取正常,保存不行。
我的代码:
class XmlDocHandler
{
private string filePath;
private XDocument xmlDoc;
private IList<XElement> updatedElements;
public IEnumerable<XElement> Elements => xmlDoc.Descendants();
public IEnumerable<XElement> UpdatedElements => updatedElements;
public XmlDocHandler(string filePath)
{
this.filePath = filePath;
ReloadFromFile();
updatedElements = new List<XElement>();
}
public void UpdateElements(IEnumerable<XElement> newElements)
{
updatedElements = new List<XElement>();
foreach (XElement newElement in newElements)
{
XElement element = xmlDoc.Descendants()
.FirstOrDefault(x => x.Name.LocalName == newElement.Name.LocalName);
if (element != null)
{
if (element.Value != newElement.Value)
{
element.Value = newElement.Value;
updatedElements.Add(element);
}
}
}
}
public void ReloadFromFile()
{
bool success = false;
if (File.Exists(filePath))
{
try
{
xmlDoc = XDocument.Load(filePath);
success = true;
}
catch
{
}
}
if (!success)
{
xmlDoc = new XDocument();
}
}
public void WriteToFile()
{
xmlDoc.Save(filePath);
}
}
据我所知,它是一组序列化的操作,没有并行或其他花哨的东西,可能会阻塞我的文件。我没有发现 XDocument.Load("c:\file.xml") 会在文件上创建锁的迹象。
我已经尝试替换直接操作
xmlDoc = XDocument.Load(filePath);
和
xmlDoc.Save(filePath);
使用此处找到的基于流的方法:
XDocument.Save() unable to access file
和这里
c# xml.Load() locking file on disk causing errors
这样它们看起来像这样:
正在加载..
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xmlDoc = XDocument.Load(fs);
}
或
using (var sr = new StreamReader(filePath))
{
xmlDoc = XDocument.Load(sr);
}
和写作..
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.Write))
{
xmlDoc.Save(fs);
}
无论我做什么,正确关闭流并确保文件未在任何编辑器中打开或以其他方式使用,愚蠢的文件始终是 "used by another process"。
我在这里到底没有看到什么?有问题的文件位于我的 .exe 文件旁边的 VS2017 Pro 调试输出文件夹中。我不知道我对该文件夹的写入权限有限。
尝试
fs.Flush();
也许
fs.Close();
写完之后。据我所知,IO 流中正在进行某种缓存。可能会有帮助。
此致。
我发现了导致这次失败的错误!
此问题的原因与 XDocument.Load()
或 .Save()
无关。在为解决我的问题而松了一口气的同时,我也很尴尬地承认我多年前自己的一个实现导致了这个问题。
我曾经为 System.Windows.Forms.OpenFileDialog()
制作了一个包装器 class,这将简化我经常使用的 OFD class 配置。在其中我使用了类似
的东西
var ofd = new OpenFileDialog();
try
{
if((var stream = ofd.OpenFile()) != null)
{
return ofd.FileName;
}
else
{
return "file already opened";
}
}
catch
{
return "error";
}
同时将 ofd
和 stream
引用保留为实例变量。现在看这段代码让我不寒而栗(或笑),但那时候我不知道更好。当然,这现在让我很痛苦,因为我没有关闭那个流!我几年前犯下的罪行现在让我花了将近 2 天的工作时间。
我的补救措施:我重写了我的 OFD 包装器 class 以使用 Microsoft.Win32.OpenFileDialog
class,因为它似乎没有任何基于流的东西会无意中锁定文件.
经验教训(以及我热烈推荐给其他人的内容):在使用流或其他可以保持打开状态并导致内存泄漏的构造时,永远不要相信自己。阅读通过调用通常负责此类清理工作的 IDisposable.Dispose()
方法来使用处置模式的 using 块语句。最后,使用 VS 中简洁的分析功能,这些功能在我制作 OFD 包装器时不可用,它们有助于发现此类问题。
感谢所有提供帮助的人,也感谢提供他们帮助的人。
我打算使用 XDocument.Load() 加载一个 xml 文件,更新一些元素的值,然后使用 XDocument.Save() 保存它。读取正常,保存不行。
我的代码:
class XmlDocHandler
{
private string filePath;
private XDocument xmlDoc;
private IList<XElement> updatedElements;
public IEnumerable<XElement> Elements => xmlDoc.Descendants();
public IEnumerable<XElement> UpdatedElements => updatedElements;
public XmlDocHandler(string filePath)
{
this.filePath = filePath;
ReloadFromFile();
updatedElements = new List<XElement>();
}
public void UpdateElements(IEnumerable<XElement> newElements)
{
updatedElements = new List<XElement>();
foreach (XElement newElement in newElements)
{
XElement element = xmlDoc.Descendants()
.FirstOrDefault(x => x.Name.LocalName == newElement.Name.LocalName);
if (element != null)
{
if (element.Value != newElement.Value)
{
element.Value = newElement.Value;
updatedElements.Add(element);
}
}
}
}
public void ReloadFromFile()
{
bool success = false;
if (File.Exists(filePath))
{
try
{
xmlDoc = XDocument.Load(filePath);
success = true;
}
catch
{
}
}
if (!success)
{
xmlDoc = new XDocument();
}
}
public void WriteToFile()
{
xmlDoc.Save(filePath);
}
}
据我所知,它是一组序列化的操作,没有并行或其他花哨的东西,可能会阻塞我的文件。我没有发现 XDocument.Load("c:\file.xml") 会在文件上创建锁的迹象。
我已经尝试替换直接操作
xmlDoc = XDocument.Load(filePath);
和
xmlDoc.Save(filePath);
使用此处找到的基于流的方法: XDocument.Save() unable to access file 和这里 c# xml.Load() locking file on disk causing errors 这样它们看起来像这样:
正在加载..
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xmlDoc = XDocument.Load(fs);
}
或
using (var sr = new StreamReader(filePath))
{
xmlDoc = XDocument.Load(sr);
}
和写作..
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.Write))
{
xmlDoc.Save(fs);
}
无论我做什么,正确关闭流并确保文件未在任何编辑器中打开或以其他方式使用,愚蠢的文件始终是 "used by another process"。
我在这里到底没有看到什么?有问题的文件位于我的 .exe 文件旁边的 VS2017 Pro 调试输出文件夹中。我不知道我对该文件夹的写入权限有限。
尝试
fs.Flush();
也许
fs.Close();
写完之后。据我所知,IO 流中正在进行某种缓存。可能会有帮助。
此致。
我发现了导致这次失败的错误!
此问题的原因与 XDocument.Load()
或 .Save()
无关。在为解决我的问题而松了一口气的同时,我也很尴尬地承认我多年前自己的一个实现导致了这个问题。
我曾经为 System.Windows.Forms.OpenFileDialog()
制作了一个包装器 class,这将简化我经常使用的 OFD class 配置。在其中我使用了类似
var ofd = new OpenFileDialog();
try
{
if((var stream = ofd.OpenFile()) != null)
{
return ofd.FileName;
}
else
{
return "file already opened";
}
}
catch
{
return "error";
}
同时将 ofd
和 stream
引用保留为实例变量。现在看这段代码让我不寒而栗(或笑),但那时候我不知道更好。当然,这现在让我很痛苦,因为我没有关闭那个流!我几年前犯下的罪行现在让我花了将近 2 天的工作时间。
我的补救措施:我重写了我的 OFD 包装器 class 以使用 Microsoft.Win32.OpenFileDialog
class,因为它似乎没有任何基于流的东西会无意中锁定文件.
经验教训(以及我热烈推荐给其他人的内容):在使用流或其他可以保持打开状态并导致内存泄漏的构造时,永远不要相信自己。阅读通过调用通常负责此类清理工作的 IDisposable.Dispose()
方法来使用处置模式的 using 块语句。最后,使用 VS 中简洁的分析功能,这些功能在我制作 OFD 包装器时不可用,它们有助于发现此类问题。
感谢所有提供帮助的人,也感谢提供他们帮助的人。