Tuesday, March 22, 2005

How to read a file that's in use by another process.


Recently I was needed to read context of some log file that's in use by another process when I trying to read from it.

It seems that there is no way to do it with System.IO.StreamReader. The stuff like:

using( System.IO.StreamReader logReader = new System.IO.StreamReader(logPath) )
{
System.String errorFileContext = updateErrorFileReader.ReadToEnd();
}


will cause System.IO.IOException with Message saying "The process cannot access the file ... because it is being used by another process."
My obvious guess was that System.IO.StreamReader doesn't have a constructor specifying the file sharing mode, so I switched to System.IO.FileStream:


using( System.IO.FileStream logReader = new System.IO.FileStream(
logFilePath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read ) )
{
// In my case it always the case, o/w you can read file line-by-line
const int maxFileSize = 10*1024;
byte[] fileBytes = new byte[maxFileSize];

int amountOfBytes = updateErrorFileReader.Read(fileBytes, 0, maxFileSize);

System.Text.UTF7Encoding utf7 = new System.Text.UTF7Encoding();

System.String errorFileContext = utf7.GetString(fileBytes, 0, amountOfBytes);
}



MSDN documentation states that setting last parameter of System.IO.FileStream constructor to System.IO.FileShare.Read:



"Allows subsequent opening of the file for reading.
If this flag is not specified, any request to open the file
for reading (by this process or another process) will fail
until the file is closed. However, if this flag is specified
additional permissions might still be needed to access the file."




Well, that's was exactly what I was going to do and ... imagine my surprise when I got the same thing again:
System.IO.IOException with "The process cannot access the file ... because it is being used by another process.".

Solution came after playing a bit around. What you need to do - is to put last parameter to
System.IO.FileShare.ReadWrite

It was quite surprising and took me some time to found it, since MSDN says that it "Allows subsequent opening of the file for reading or writing." while I was need reading only. Any way it just works...

7 comments:

Mark said...

I know this is an older posting, but I just found it. :) Your solution worked great for me, and after reading the Microsoft "subsequent" line, it made sense. Any file access to the file AFTER (or subsequently to) your process will have Read/Write. If it were only Read, then subsequent processes could only Read the file. I hope this makes sense to someone else! Thanks for the post.

Anonymous said...

That's just worked for me as well (VS 2008)... I can kind of understand the logic in it but cannot quite understand why Microsoft didn't make ReadWrite the default!

Anonymous said...

Thanks! just by adding "FileShare.ReadWrite" I can fix a problem that has been a known issue in our app for years.

Salaciak said...

Thanks for solving this puzzle :)

Anonymous said...

Also very thanks! I almost did File.Copy(...) for that issue, but thanks to you (Anonymous) it works great!

Thanks again!

Anonymous said...

Solved my problem, thanks!

I just took the FileStream and used it in the StreamReader's constructor.

Anonymous said...

That did the trick. Thank you so much!