Home > Software engineering >  Error when deleting a file after Xdocument Load
Error when deleting a file after Xdocument Load

Time:05-25

So.... Basically I need to create a little program that will convert XML data to CSV. I have everything done...almost

All of the code runs great, there is only one problem. As soon as everything is done, I want the xml file to be deleted. Although it won't really let me throwing me an error on the Xdocument.Load line.

As soon as the file gets deleted, the Xdocument.Load is telling me that it can't find the file, but everything is done, I don't need it to try to load the file that has been deleted...

Here's most of my code :

        static void Main()
    {
        
        using var watcher = new FileSystemWatcher(@"C:\Users\Steven\Documents\XML");

        watcher.NotifyFilter = NotifyFilters.Attributes
                             | NotifyFilters.CreationTime
                             | NotifyFilters.DirectoryName
                             | NotifyFilters.FileName
                             | NotifyFilters.LastAccess
                             | NotifyFilters.LastWrite
                             | NotifyFilters.Security
                             | NotifyFilters.Size;

        watcher.Changed  = OnChanged;
        watcher.Created  = OnCreated;
        watcher.Deleted  = OnDeleted;
        watcher.Renamed  = OnRenamed;
        watcher.Error  = one rror;

        watcher.Filter = "*.xml";
        watcher.IncludeSubdirectories = true;
        watcher.EnableRaisingEvents = true;

        Console.WriteLine("Press enter to exit.");
        Console.ReadLine();
    }


            private static void OnChanged(object sender, FileSystemEventArgs e)
    {
        if (e.ChangeType != WatcherChangeTypes.Changed)
        {
            return;
        }
        StringBuilder sb = new();
        string delimiter = ",";
        string path = $"{e.FullPath}";
        XDocument loadInvoices = XDocument.Load(path);
        string invoiceText = loadInvoices.ToString();
        var invoice = XElement.Parse(invoiceText);
        string supplierName = "";
        string invoicePO = "";


        sb.Append("Supplier"   delimiter);

        foreach (var item in invoice.Descendants("Fields").Descendants("Field").ToList())
        {
            sb.Append(item.Attribute("Name").Value.Replace("é","e")  delimiter);
        }
        sb.AppendLine();
        foreach (var item in invoice.Descendants("Supplier").ToList())
        {
            supplierName = item.Element("Name").Value;
            sb.Append(supplierName   delimiter);
        }
        foreach (var item in invoice.Descendants("Fields").Descendants("Field").ToList())
        {
            string temp = item.Attribute("Type").Value;
            if (temp != "invoiceordernumber")
            {               
                sb.Append(item.Value   delimiter);
            }
            else
            {
                invoicePO = item.Value;
                sb.Append(item.Value   delimiter);
            }
            
        }

        
        StreamWriter sw = new StreamWriter(@"C:\Users\Steven\Documents\XML\"  supplierName  "_PO#"  invoicePO   ".csv");
         sw.WriteLine(sb.ToString());
        sw.Close();
        loadInvoices = null;
        File.Delete(path);

        
    }

    private static void OnCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine("File "   e.FullPath   " started copying : "   DateTime.Now.ToString());

        while (true)
        {
            try
            {
                FileStream fileStream = File.Open(e.FullPath, FileMode.Open, FileAccess.Read);
                Console.WriteLine("File is copied : "   DateTime.Now.ToString());
                fileStream.Close();
                
                //there is the point when the file is completed copying .... now you should be able to access the file and process it.
                return;
            }
            catch (IOException ioException) { }


        }
    }

    private static void OnDeleted(object sender, FileSystemEventArgs e) =>
        Console.WriteLine($"Deleted: {e.FullPath}");

    private static void OnRenamed(object sender, RenamedEventArgs e)
    {
        Console.WriteLine($"Renamed:");
        Console.WriteLine($"    Old: {e.OldFullPath}");
        Console.WriteLine($"    New: {e.FullPath}");
    }

    private static void one rror(object sender, ErrorEventArgs e) =>
        PrintException(e.GetException());

    private static void PrintException(Exception? ex)
    {
        if (ex != null)
        {
            Console.WriteLine($"Message: {ex.Message}");
            Console.WriteLine("Stacktrace:");
            Console.WriteLine(ex.StackTrace);
            Console.WriteLine();
            PrintException(ex.InnerException);
        }
    }
}

Please help :(

CodePudding user response:

This looks like a problem caused by running this code in a loop or some other way that causes it to be re-run after it has been completed.

I recommend you try to debug and see what is happening there and why it's re-run.

Other than that, it's a good idea to check if the file exists before loading it:

if (!File.Exists(path))
    return;
XDocument loadInvoices = XDocument.Load(path);

This will check if the file exists, if it doesn't then it will exit whatever function your code is in, otherwise, it will continue.

This will probably solve your problem here as it will prevent the code from opening deleted file.

CodePudding user response:

The FileWatcher will fire a change event when you delete the file, so it's re-calling your OnChanged event handler after the file is gone. This is why your load operation fails.

You can put an if File.Exists(path) in there when you attempt to load your XML as the one of the comments recommended, or, after deletion, remove the OnChanged event delegate from the FileWatcher.

  • Related