程序生成的 xml 文件上的共享冲突

本文关键字:共享 冲突 文件 xml 程序生成 | 更新日期: 2023-09-27 18:35:27

我正在使用monodevelop编写一个C#控制台应用程序,最近我决定使用xml文件作为存储用户首选项的方式。创建、写入初始数据和读取文件很容易完成,从我所看到的更新来看,更新它也应该如此。但是,下面的代码会在路径上生成共享冲突:

public void Update (string username, PreferenceAttribute preferencename, string newvalue)
    {
        try 
        {
            ...
            //this is where it throws exception '/
            using (FileStream fs = new FileStream (filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                string attribute = preferencename.ToString ();
                doc = new XmlDocument ();
                doc.Load (fs);
                fs.Close ();
                XmlNode user = doc.SelectSingleNode ("//Users/User[@Name = '" + username + "']");
                XmlNode pref = user.SelectSingleNode("Pref");
                pref.Attributes[attribute].Value = newvalue;
                doc.Save (fs);
            }
        } catch (Exception ex)
        {
            //error details output
        }
    }

省略 using 块会导致错误发生在 doc.save(fs) 行,还会导致文件丢失任何数据。我看过其他帖子,但唯一的解决方案似乎是使用块。我需要一种方法来锁定文件(除非我的代码产生了问题)。有什么帮助吗?

编辑:

这是我尝试编辑的xml文档:

<?xml version="1.0" encoding="utf-8"?>
<!--Do not modify this auto-generated file. Doing so will cause unwanted behavior. If modification causes problems, delete this file and rerun the program-->
<Users>
  <User Name="Ben" Password="hello54">
    <Pref Gender="Male" Admin="false" Butler="Alfred" Eastereggs="false" />
  </User>
  <User Name="Admin" Password="admin">
    <Pref Gender="Male" Admin="true" Butler="Butler" Eastereggs="false" />
  </User>
</Users>

认识到以这种方式存储密码和东西是不安全的;但是,我是一个业余爱好者,试图学习xml并发展我的C#技能,所以暂时没关系。

堆栈跟踪:

Sharing violation on path /Users/Knoble/MonoProjects/Test_Console/Test_Console/bin/Debug/Preferences.xml
mscorlib
  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) [0x0032f] in /private/tmp/source-mono-mac-3.10.0-branch/bockbuild-mono-3.10.0-branch/profiles/mono-mac-xamarin/build-root/mono-3.10.0/mcs/class/corlib/System.IO/FileStream.cs:320 
  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share) [0x00000] in /private/tmp/source-mono-mac-3.10.0-branch/bockbuild-mono-3.10.0-branch/profiles/mono-mac-xamarin/build-root/mono-3.10.0/mcs/class/corlib/System.IO/FileStream.cs:132 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
  at XMLPref.XMLPreferences.Update (System.String username, PreferenceAttribute preferencename, System.String newvalue) [0x0003d] in /Users/Knoble/MonoProjects/Test_Console/XMLPreferences/XMLPreferences.cs:299 
Void .ctor(String, FileMode, FileAccess, FileShare, Int32, Boolean, FileOptions)

程序生成的 xml 文件上的共享冲突

你的代码有两个问题。

如果你要求对你的文件进行写访问(FileAccess.ReadWrite),你不能允许其他流/线程/程序同时读取(FileShare.Read)它。

问题是,一旦你Close Stream(例如FileStream,你就不能再读/写它了)。您向操作系统发出信号,表明该文件现在可以由其他程序使用。

该问题的潜在解决方案是使用该文件两次:

using (FileStream fs = new FileStream (filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
    string attribute = preferencename.ToString ();
    doc = new XmlDocument ();
    doc.Load (fs);
}
XmlNode user = doc.SelectSingleNode ("//Users/User[@Name = '" + username + "']");
XmlNode pref = user.SelectSingleNode("Pref");
pref.Attributes[attribute].Value = newvalue;
using (FileStream fs = new FileStream (filepath, FileMode.Open, FileAccess.Write, FileShare.None)) {
    doc.Save (fs);
}

您可以将第二部分替换为:

doc.Save (filepath);