我正在使用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)
答案 0 :(得分:2)
您的代码存在两个问题。
如果您要求对文件(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);