Search code examples
c#xmlfilestreamopenfiledialogsavefiledialog

File can't be accessed because it's being used by another process


I am creating a program that creates, writes, and saves an xml file. When I try to open the saved file I get an error that says the file cannot be accessed because it is being used by another process. I assumed it was because I didn't close the filestream after I saved the file so I made the correction. I still can't open the file and I receive the same error. I'm not sure what the issue is beyond this point. How can I fix this?

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 taken well...I refactored the code and see the error you referred to. I checked out the two links you provided as examples. I made corrections but I still get the same result.


Solution

  • First change the way you open the file to:

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

    an then try to check (Debug) the entire Exception in openToolStripMenuItem_Click event:

    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: 
    

    Then read:

    xmlns='' was not expected when deserializing nested classes

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

    Update:

    You need an atomic object when desalinizing like:

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

    and I would suggest to get rid of xDocument, DataSet & DataTable. they add too much complication for nothing. and I guess the reason u r using them because of DataGrid which is minor concern, focus on coding first:

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