Search code examples
c#file-io

How can I read a text file without locking it?


I have a windows service writes its log in a text file in a simple format.

Now, I'm going to create a small application to read the service's log and shows both the existing log and the added one as live view.

The problem is that the service locks the text file for adding the new lines and at the same time the viewer application locks the file for reading.

The Service Code:

void WriteInLog(string logFilePath, data)
{
    File.AppendAllText(logFilePath, 
                       string.Format("{0} : {1}\r\n", DateTime.Now, data));
}

The viewer Code:

int index = 0;
private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                using (StreamReader sr = new StreamReader(logFilePath))
                {
                    while (sr.Peek() >= 0)  // reading the old data
                    {
                        AddLineToGrid(sr.ReadLine());
                        index++;
                    }
                    sr.Close();
                }

                timer1.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


private void timer1_Tick(object sender, EventArgs e)
        {
            using (StreamReader sr = new StreamReader(logFilePath))
            {
                // skipping the old data, it has read in the Form1_Load event handler
                for (int i = 0; i < index ; i++) 
                    sr.ReadLine();

                while (sr.Peek() >= 0) // reading the live data if exists
                {
                    string str = sr.ReadLine();
                    if (str != null)
                    {
                        AddLineToGrid(str);
                        index++;
                    }
                }
                sr.Close();
            }
        }

Is there any problem in my code in reading and writing way?

How to solve the problem?


Solution

  • You need to make sure that both the service and the reader open the log file non-exclusively. Try this:

    For the service - the writer in your example - use a FileStream instance created as follows:

    var outStream = new FileStream(logfileName, FileMode.Open, 
                                   FileAccess.Write, FileShare.ReadWrite);
    

    For the reader use the same but change the file access:

    var inStream = new FileStream(logfileName, FileMode.Open, 
                                  FileAccess.Read, FileShare.ReadWrite);
    

    Also, since FileStream implements IDisposable make sure that in both cases you consider using a using statement, for example for the writer:

    using(var outStream = ...)
    {
       // using outStream here
       ...
    }
    

    Good luck!