tags:

views:

220

answers:

6

Hi,

I've a windows service writes its log in a text file in a simple format, Now, I'm going to create a small software to read the service's log and show the existing log and the added as live view,

the problem is when the service will lock the text file while adding the new lines, and the viewer application will lock the file while 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))
            {
                for (int i = 0; i < index ; i++) // skipping the old data, it has read in the Form1_Load event handler
                    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 can I prevent the problem ?

Thanks in advance.

+1  A: 

Have you tried copying the file, then reading it?

Just update the copy whenever big changes are made.

Tom Gullen
+1  A: 

The problem is when you are writing to the log you are exclusively locking the file down so your StreamReader won't be allowed to open it at all.

You need to try open the file in readonly mode.

Have you tried File.ReadAllText? Not sure if that opens in read only mode by default otherwise try something like:

FileStream logFileStream = 
using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (StreamReader sr = new StreamReader(fs))
    {
        while (!logFileReader.EndOfStream)
        {
            string line = logFileReader.ReadLine();
            // Your code here
        }
    }
}
James
+5  A: 

Explicit set up the sharing mode while reading the text file.

using (FileStream fs = new FileStream(logFilePath, FileMode.Open, FileAccess.Read,    
FileShare.ReadWrite))
        {
            using (StreamReader sr = new StreamReader(fs))
            {
                while (sr.Peek() >= 0) // reading the old data
                {
                    AddLineToGrid(sr.ReadLine());
                    index++;
                }
                sr.Close();
            }
        }
heads5150
it is unnecessary to explicitly close the stream, as StreamReader.Dispose closes it automatically.
Yossarian
I believe the file share should be set on BOTH read and write streams, and not only read.
L.E.O
+6  A: 

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

For the service 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);

Good luck!

John
+1  A: 
new StreamReader(File.Open(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))

-> this doesn't lock the file.

Yossarian
+1  A: 

I remember doing the same thing a couple of years ago. After some google queries i found this:

    FileStream fs = new FileStream(@”c:\test.txt”, 
                                   FileMode.Open, 
                                   FileAccess.Read,        
                                   FileShare.ReadWrite);

i.e. use the FileShare.ReadWrite attribute on FileStream().

(found on Balaji Ramesh's blog)

dotmartin