Question Best way to stop exception when you delete a file that was supposed to be read?

Wowywow

Member
Joined
Nov 9, 2019
Messages
16
Programming Experience
Beginner
Hello, first step of many in this exercise is that I need to check if file exist and just display that in label element, which is easy enough. The problem appears when I try to read that file, as long as the file exist there is works, but when I delete it "StreamReader" throws an exception ( System.IO.FileNotFoundException ).
C#:
string filePath = System.IO.Directory.GetCurrentDirectory() + @"\txt1.txt";
string data;
using (var streamReader = new System.IO.StreamReader(filePath))
{
    data = streamReader.ReadToEnd();
}
What I need it to do is to display "File doesn't exist" in the same label element, for that I was using File.Exist();
Whats the best way to deal with it? Catch and try blocks or something simplier?
 
You'll need to show us the context where you are deleting the file. Are you deleting the file while the StreamReader is still open and active? If so, that will obviously fail.

Anyway, if all you need is to read all the file contents as a single string, why even use a StreamReader? Just use File.ReadAllText().
 
Last edited:
You should ALWAYS use exception handling when working with things that are beyond your control. Even if you call File.Exists and it returns True, there's still a slim possibility that the file could be deleted or locked between that and when you try to open it. In this case, that means that you should be calling File.Exists first and then opening the file inside a Try block if it returns True.
 
If it is your intention to get the path of a file in the same folder as your EXE then you should use Application.StartupPath, assuming a Windows GUI app. The current directory may or may not start out as the folder containing the EXE and it can change over the course of the session.
 
You'll need to show us the context where you are deleting the file.
C#:
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        class readFile
        {
            public string readData(Label lbl)
            {
                string file = System.IO.Directory.GetCurrentDirectory() + @"\txt1.txt";
                string data;
                if (File.Exists(file))
                {
                    lbl.Text = "failas yra";
                    data = File.ReadAllText(file);
                }
                else
                {
                    lbl.Text = "failo nera";
                }
                return data;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            readFile rf = new readFile();
            rf.readData(label1);
        }
    }
}
Right... so I keep getting new error: Use of unassigned local variable 'data', I need to return that 'data' to any event ( like button click or form load ). It's probably very stupid mistake
 
In your code, you have string data;. Try string data = string.Empty; , and you will find that problem is gone. Try this :

This will give you the application directory of the application startup path. It's my preference to use when interacting with files in the executable files directory.
C#:
        private static readonly string FilePath = Path.Combine(Application.StartupPath, "txt1.txt");
However, you can also use these :
C#:
        private static readonly string FilePath_A = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "txt1.txt");
        private static readonly string FilePath_B = Path.Combine(Environment.CurrentDirectory, "txt1.txt");
        private static readonly string FilePath_C = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "txt1.txt");
Which also return the same value but this depends on the type of project and the Environment therein.

I've added some error logging but you can remove it if you want :
C#:
        private static readonly string ErrorLog = FilePath.Replace(Path.GetFileName(FilePath), "errorlog.log");
You will find the logging is done in the catch block for the ArrayList ReadDataToArrayList(string address) method further below.

I've used an ArrayList just in case you want to work with multiple files now or later :
C#:
        private static readonly ArrayList ArrList = new ArrayList();

Next we will set one label which is label1.Text and this will state if the file exists or not through button1 click event. It will also call the ReadDataToArrayList(FilePath) method to read from the file. Modify to your liking :
C#:
        private void Button1_Click(object sender, EventArgs e)
        {
            bool condition = File.Exists(FilePath);
            if (condition) { label1.Text = $"File Exists : {condition}"; ReadDataToArrayList(FilePath); }
            else { label1.Text = $"File Exist : {condition}"; }
        }

Button2 click event sets the text property of label2 if the ArrList is not empty and it currently only gets the first item in the list. If the ArrList has no items, it will report there was nothing to read. Adapt to your liking or needs :
C#:
        private void button2_Click(object sender, EventArgs e)
        {
            if (ArrList.Count > 0)
                label2.Text = ArrList[0].ToString();
            else label2.Text = "There was nothing to read.";
            ArrList.Clear();
        }

Button3 click event allows you to search ArrList for a word pattern. It gets this pattern from textbox1.Text property. This allows you to search the array list and return an item matching the keyword in textbox1. I added this as I thought it might be useful for you. But you don't need to use it if you don't want too :
C#:
        private void button3_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < ArrList.Count; i++)
            {
                if (ArrList[i].ToString().Contains(textBox1.Text))
                    label2.Text = ArrList[i].ToString();
                else label2.Text = "No matches found.";
            }
        }

And the important part is the method that populates out array with the text that is read from your file. If the data has been populated, the length will be more than 0 and providing the ArrList does not contain the same text as what you are reading, it will then add the text from your text file to your ArrList. If you remove the file after pressing button1, you will also find that the exception will be caught and an error log will be wrote to the executing directory. (Should be noted, if running this error log from within Program Files, you likely will be required to execute with elevated permissions.) But for testing, it works well.

C#:
        private static ArrayList ReadDataToArrayList(string address)
        {
            try
            {
                string data = File.ReadAllText(address);
                if (data.Length > 0 && !ArrList.Contains(data))
                    ArrList.Add(data);
            }
            catch (Exception ex)
            {
                /* Handle error or write error log */
                File.AppendAllText(ErrorLog, string.Concat(Environment.NewLine, $"Exception Message : ",
                    $"{string.Concat(Environment.NewLine, ex.Message, Environment.NewLine, "Exception Stack : ", Environment.NewLine, ex.StackTrace)} "));
                return ArrList;
            }
            return ArrList;
        }
All together, you will have :
C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private static readonly string FilePath = Path.Combine(Application.StartupPath, "txt1.txt");

        private static readonly string ErrorLog = FilePath.Replace(Path.GetFileName(FilePath), "errorlog.log");
        private static readonly ArrayList ArrList = new ArrayList();

        private static ArrayList ReadDataToArrayList(string address)
        {
            try
            {
                string data = File.ReadAllText(address);
                if (data.Length > 0 && !ArrList.Contains(data))
                    ArrList.Add(data);
            }
            catch (Exception ex)
            {
                /* Handle error or write error log */
                File.AppendAllText(ErrorLog, string.Concat(Environment.NewLine, $"Exception Message : ",
                    $"{string.Concat(Environment.NewLine, ex.Message, Environment.NewLine, "Exception Stack : ", Environment.NewLine, ex.StackTrace)} "));
                return ArrList;
            }
            return ArrList;
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            bool condition = File.Exists(FilePath);
            if (condition) { label1.Text = $"File Exists : {condition}"; ReadDataToArrayList(FilePath); }
            else { label1.Text = $"File Exist : {condition}"; }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (ArrList.Count > 0)
                label2.Text = ArrList[0].ToString();
            else label2.Text = "There was nothing to read.";
            ArrList.Clear();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < ArrList.Count; i++)
            {
                if (ArrList[i].ToString().Contains(textBox1.Text))
                    label2.Text = ArrList[i].ToString();
                else label2.Text = "No matches found.";
            }
        }
    }

Hope this helps.
 
Last edited:
Back
Top Bottom