【问题标题】:File can't be accessed because it's being used by another process无法访问文件,因为它正被另一个进程使用
【发布时间】:2018-03-27 10:49:32
【问题描述】:

我正在创建一个创建、写入和保存 xml 文件的程序。当我尝试打开保存的文件时,我收到一条错误消息,指出无法访问该文件,因为它正在被另一个进程使用。我认为这是因为我在保存文件后没有关闭文件流,所以我进行了更正。我仍然无法打开文件,并且收到相同的错误。我不确定超出这一点的问题是什么。我该如何解决这个问题?

namespace XML_DataSets
{
    public partial class FormAddNew : Form
    {
        XmlSerializer xs;
        List<Class1> ls;

        //create the DataTable
        DataTable dt = new DataTable("Contact");
        XDocument xd = new XDocument();

        public FormAddNew()
        {
            InitializeComponent();

            ls = new List<Class1>();
            xs = new XmlSerializer(typeof(List<Class1>));

            //create columns for the DataTable
            DataColumn dc1 = new DataColumn("Id");
            dc1.DataType = System.Type.GetType("System.Int32");
            dc1.AutoIncrement = true;
            dc1.AutoIncrementSeed = 1;
            dc1.AutoIncrementStep = 1;

            //add columns to the DataTable
            dt.Columns.Add(dc1);
            dt.Columns.Add(new DataColumn("Name"));
            dt.Columns.Add(new DataColumn("Age"));
            dt.Columns.Add(new DataColumn("Gender"));

            //create DataSet
            DataSet ds = new DataSet();
            ds.DataSetName = "AddressBook";
            ds.Tables.Add(dt);
        }


        private void buttonCreate_Click(object sender, EventArgs e)
        {
            DataRow row = dt.NewRow();
            row["Name"] = textBoxName.Text;
            row["Age"] = textBoxAge.Text;
            row["Gender"] = textBoxGender.Text;

            dt.Rows.Add(row);
            dataGridView1.DataSource = dt;

            //dt.WriteXml("Contacts.xml");
            xd = WriteDt2Xml(dt);
        }

        public static XDocument WriteDt2Xml(DataTable dt)
        {
            using (var stream = new MemoryStream())
            {
                dt.WriteXml(stream);
                stream.Position = 0;
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.ConformanceLevel = ConformanceLevel.Fragment;
                XmlReader reader = XmlReader.Create(stream, settings);
                reader.MoveToContent();
                if (reader.IsEmptyElement) { reader.Read(); return null; }
                return XDocument.Load(reader);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stream input = null;
            OpenFileDialog dialog = new OpenFileDialog();
            openFileDialog.Filter = "xml file | *.xml";
            openFileDialog.FilterIndex = 2;
            openFileDialog.RestoreDirectory = true;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if ((input = openFileDialog.OpenFile()) != null)
                    {
                        FileStream fs = new FileStream(@openFileDialog.FileName.ToString(), FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                        ls = (List<Class1>)xs.Deserialize(fs);
                        dataGridView1.DataSource = ls;
                        fs.Close();

                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "ERROR");
                }
            }
        }
    }
}

@Daniel Advise 做得好...我重构了代码并看到了您提到的错误。我查看了您作为示例提供的两个链接。我进行了更正,但仍然得到相同的结果。

【问题讨论】:

  • 快速猜测:XmlReader reader 永远不会被处理掉。
  • 除了@mayu 的建议之外,如果您重新启动计算机然后除了清理、重建并运行它什么也不做,您是否会收到错误?
  • @Missy...是的,这是正确的。我目前正在研究连载,看看我哪里出错了。
  • @mayu - XmlReader 阅读器被包装在 Using...中,因此一旦 Using 完成,任何与它相关的进程都应该被处理掉。
  • @Daniel ...感谢您的所有帮助...此解决方案有效。我使用数据集、表和网格的原因是因为我一遍又一遍地构建相同的解决方案,以便我可以牢牢掌握 xml。感谢您的帮助和时间。干杯!

标签: c# xml filestream openfiledialog savefiledialog


【解决方案1】:

先把打开文件的方式改成:

using (var fs = new FileStream(@openFileDialog.FileName, FileMode.Open, FileAccess.Read))
{
    ls = (List<Class1>) xs.Deserialize(fs);
    dataGridView1.DataSource = ls;
}

然后尝试检查(调试)openToolStripMenuItem_Click 事件中的整个异常:

System.InvalidOperationException was caught
  HResult=-2146233079
  Message=There is an error in XML document (2, 2).
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)
       at WindowsFormsApplication1.FormAddNew.openToolStripMenuItem_Click(Object sender, EventArgs e) in c:\Users\admin\Documents\Visual Studio 2013\Projects\WindowsFormsApplication1\WindowsFormsApplication1\FormAddNew.cs:line 131
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=<AddressBook xmlns=''> was not expected. --The problem!
       Source=Microsoft.GeneratedCode
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read3_ArrayOfClass1()
       InnerException: 

然后阅读:

xmlns='' was not expected when deserializing nested classes

{"<user xmlns=''> was not expected.} Deserializing Twitter XML

更新:

淡化时需要一个原子对象,例如:

public class AddressBook
{
    public AddressBook()
    {
        Contacts = new List<Contact>();
    }

    public List<Contact> Contacts { get; set; }
}

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Age { get; set; }
    public string Gender { get; set; }
}

我建议摆脱 xDocument、DataSet 和 DataTable。他们无缘无故地增加了太多的复杂性。我猜你使用它们的原因是因为 DataGrid 是次要问题,首先关注编码:

private readonly XmlSerializer xs;
private AddressBook ls;
private int _counter = 0;

public FormAddNew2()
{
    InitializeComponent();

    ls = new AddressBook();
    xs = new XmlSerializer(typeof(AddressBook));
}

private void buttonCreate_Click(object sender, EventArgs e)
{
    var addressBookContact2 = new Contact
    {
        Id = ++_counter,
        Name = textBoxName.Text,
        Age = textBoxAge.Text,
        Gender = textBoxGender.Text
    };

    ls.Contacts.Add(addressBookContact2);

    dataGridView1.DataSource = null; // strangly u need this
    dataGridView1.DataSource = ls.Contacts;
}

private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
    var saveFileDialog = new SaveFileDialog();
    saveFileDialog.InitialDirectory = @"C:\";
    saveFileDialog.RestoreDirectory = true;
    saveFileDialog.Title = "Select save location file name";
    saveFileDialog.Filter = "XML-File | *.xml";
    if(saveFileDialog.ShowDialog() == DialogResult.OK)
    {
        using(var writer = new StreamWriter(saveFileDialog.FileName))
        {
            xs.Serialize(writer, ls);
            MessageBox.Show(saveFileDialog.FileName);
        }
    }
}

private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
    var openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "xml file | *.xml";
    openFileDialog.FilterIndex = 2;
    openFileDialog.RestoreDirectory = true;

    if(openFileDialog.ShowDialog() == DialogResult.OK)
    {
        try
        {
            using (var reader = new StreamReader(@openFileDialog.FileName))
            {
                ls = (AddressBook) xs.Deserialize(reader);
                _counter = 0;
                dataGridView1.DataSource = ls.Contacts;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString(), "ERROR");
        }
    }
}

【讨论】:

  • @Daniel...我正在研究这个。我会发布我发现的内容
  • @tony 如果您发布 Class1 代码会很有帮助。我猜自己
  • @Daniel...我发布了...这让我发疯了。
  • 首先解决这个问题:使用 (var fs = new FileStream(@openFileDialog.FileName, FileMode.Open, FileAccess.Read)) { ls = (List) xs.Deserialize(fs); dataGridView1.DataSource = ls; }
  • @Daniel...我尝试了建议的更改,得到了相同的结果。只是为了澄清,您是否看到 openfiledialog 有问题?正如我所说,建议的更改产生了相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 2011-07-05
  • 2015-12-07
相关资源
最近更新 更多