6

My application parses log files but when trying to parse the current day's file I get an error stating that the file is being used by another process. This log file is currently being written to and can be accessed through notepad but not through my application.

Current Code:

Stream stream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(stream);

Also tried this but had no luck:

Stream stream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

What changes need to be to my code in order to READ a file that is being used by another process. Copying the log file is not a solution due to the size of the log and performance of my application

SlopTonio
  • 1,105
  • 1
  • 16
  • 39
  • 1
    See this http://stackoverflow.com/questions/660019/opening-a-files-shadow-copy-if-the-current-copy-is-in-use – LostInComputer May 09 '14 at 08:04
  • Have you looked at the overloaded constructor that takes a FileShare (A constant that determines how the file will be shared by processes) –  May 09 '14 at 08:08
  • I tried: Stream stream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read, FileShare.Read); But no luck – SlopTonio May 09 '14 at 08:12
  • If the file is being *written* to by another process, you need to specify (at least) `FileShare.Write`. `FileShare` says what you're happy for *other* users to be doing to the file. Of course, this will still fail if the other process hasn't specified (the equivalent of) `FileShare.Read` when they opened the file. – Damien_The_Unbeliever May 09 '14 at 08:17
  • I've tried FileShare.Read, FileShare.Write and FileShare.ReadWrite but had no luck. Any other suggestions? – SlopTonio May 09 '14 at 08:20
  • 1
    You've said that Notepad can open the file fine but your code can't. Use [Process Monitor](http://technet.microsoft.com/en-gb/sysinternals/bb896645.aspx) to examine the different ways that your code and notepad open the file, and add that information to your question (if it's not, then, obvious to you how to fix your code to act in the same way that notepad does) – Damien_The_Unbeliever May 09 '14 at 08:27
  • Try opening the file with the `FileAccess` level of previous open commands `FileShare` level. – Tolga Evcimen May 09 '14 at 08:34

3 Answers3

10

We can use a different signature for opening the filestream with read/write access to other processes:

Stream stream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read,
                        FileShare.ReadWrite);

or

Stream stream = File.Open(fileToRead, FileMode.Open, FileAccess.Read,
                        FileShare.ReadWrite);

The FileShare option determines how other processes can access the same file when this process opens the same file.

Your first code block will default to FileShare.None:

Stream stream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read);

This would fail whilst the file is open as it's trying to obtain exclusive access to the file.

However, you would need this to occur in the log writer to allow your log reader to have read access.

Lastly, try running your log reader as an administrator, as there may be operating system permissions at play that are not obvious when you "open with notepad".

Kevin Hogg
  • 1,771
  • 25
  • 34
  • I've tried FileShare.Read, FileShare.Write and FileShare.ReadWrite but had no luck. Any other suggestions? – SlopTonio May 09 '14 at 08:21
  • As mentioned you need the log writer to open the file stream with FileShare.Read; check the log writer code and determine if it uses FileShare.Read when creating the new log file. – Kevin Hogg May 09 '14 at 08:25
  • My program does not write/create this log file that I cannot access. It is being written to by one of my company websites. I do not have access to that code. – SlopTonio May 09 '14 at 08:34
  • 1
    **Beware of a bug**: I was getting the same error; after a long research the reason turned out that subsequent opening of a file with access with less FileShare leads to an Exception. *(in my case the file first opened as a `FileStream` with `FileShare.ReadWrite`, next opened again as a `using (var stream = File.OpenRead(file))`, it didn't have the option, but most probably it sets it to `None`)* – Hi-Angel Sep 27 '16 at 16:29
1

Here is a code snippet

The problem is when another application opens it first and the file sharing is Read only (FileShare.Read) certainly you can't write onto the file but you can read, Or file sharing is Write only (FileShare.Write) you can't Read onto the file but still you can be write onto it.

 using (FileStream file = new FileStream("You File Name here", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            using (StreamReader sr = new (StreamReader (file))
            {
        //Do your codes here     
            }
        }
Jade
  • 2,972
  • 1
  • 11
  • 9
  • I tried the above code but instead of StreamWriter I'm using StreamReader because I am trying to read the file not write to it. I am still unable to access the file – SlopTonio May 09 '14 at 08:55
  • @SlopTonio, see my updates – Jade May 09 '14 at 09:04
  • 1
    as I previously commented, I tried that but still unable to access the file. It's weird because notepad can open the log file but my application can't – SlopTonio May 09 '14 at 09:07
1

I had a similar problem that was resolved by setting the file attributes.

File.SetAttributes(outputDirectory + fileName + ".txt", FileAttributes.Normal);

This was done after the file was created, though. The problem has to do with how the OS manages files that are being accessed by multiple processes. In my case, I deleted the file (you aren't always allowed to do this because you'll get the error you're seeing). The only real way to solve this is to track down the processes that are accessing the file and stop them. The easiest way I fix this is restarting my PC, but if you are working on a server, that isn't feasible to do.

I haven't done an extensive amount of testing, but if you wanted to get this to be used by multiple processes, maybe it might be a good idea to give the file read properties and/or attributes:

File.SetAttributes(outputDirectory + fileName + ".txt", FileAttributes.ReadOnly);

Good luck - hope this helps someone else out there (since this is already a year old!).

cr1pto
  • 539
  • 3
  • 13