views:

5549

answers:

5

Hello everyone,

I want to open a file for read in exclusive mode, and if the file is already opened by some process/thread else, I want to receive an exception. I tried the following code, but not working, even if I opened the foo.txt, I still can reach the Console.WriteLine statement. Any ideas?

static void Main(string[] args)
{
    using (Stream iStream = File.Open("c:\\software\\code.txt", FileMode.Open,
    FileAccess.Read, FileShare.None))
    {
        Console.WriteLine ("I am here");
    }

    return;
}

thanks in advance, George

+1  A: 

I would suggest using the FileAccess.ReadWrite member because some files may already be open but allow you Read access on the file. However, I would guess that in non-exceptional conditions, all files open for Read/Write access would not allow your code to Write to the file.

Of course (as Mehrdad already explained), if you are using an editor such as Notepad to open the file as a test, you will not be able to restrict access because Notepad does not lock the file at all.

Cerebrus
Thanks Cerebrus, you are correct and I am using notepad to open it and run my program to test. Any ideas to check whether a file is opened or not (for example, I want my code to be able to check whether notepad has opened it)?
George2
No, I don't think there is... except by catching the IOException in the code that tries to subsequently read the file.
Cerebrus
My situation is, a thread is serialization (using XML serialization) to the file, another reader thread is read from this file. I do not want the reader thread to operate on this file while XML serialization is in process, any ideas?
George2
+3  A: 

What you are doing is the right thing. Probably you are just testing it incorrectly. You should open it with a program that locks the file when it's open. Notepad wouldn't do. You can run your application twice to see:

static void Main(string[] args)
{
    // Make sure test.txt exists before running. Run this app twice to see.
    File.Open("test.txt", FileMode.Open, FileAccess.Read, FileShare.None);
    Console.ReadKey();
}
Mehrdad Afshari
Thanks Mehrdad, anyway to check whether a file is already opened by other thread/process?
George2
I don't think there is a way to find out if a process has opened a file and is working on it. Technically, the file is no longer open after notepad loads it to memory. I think this is the right way to do it as notepad or other programs can't open it again (to read or save) which is fine, I think.
Mehrdad Afshari
Thanks Mehrdad, I have tested you are correct. my situation is, a thread is serialization (using XML serialization) to the file, another reader thread is read from this file. I do not want the reader thread to operate on this file while XML serialization is in process, any ideas?
George2
This already does achieve it. You'll get IOException if a thread is reading from the file and reader threads will get IOException if they try to open the file while you are writing to it.
Mehrdad Afshari
Hi Mehrdad, I am using XML Serialization, I am not sure if I need some special settings in order to let the serialization thread locks the file, so that the other reader thread is blocked when using FileShare.None?
George2
If you want to *block* the thread, instead of throwing the exception, you'd better use a syncronization mechanism in your application instead of OS file locking. You could use ReaderWriterLock on a shared File object: http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx
Mehrdad Afshari
I have one thread write files with arbitrary file name, another thread read scan the dictionary to read, it is hard to predict the file name also hard to synchronize. Any comments or suggestions
George2
Oh, you have many files? Have you considered using a storage engine for that matter? An RDBMS, probably...
Mehrdad Afshari
File is very big so using RDBMS is not very efficient. (continued)
George2
my situation is, one thread is copying file (using File.Move method), and another thread is read from the file. I do not want the reader thread to read a partial of the file while copy is in process(this is why I want to have exclusive open mode), does my code posted solve this issue?
George2
It does work in terms of not allowing two operations to be done simultaneously. The problem is that this solution does not *block*. It throws an exception on the thread accessing a locked file. This is why I suggest using a `lock(someObject) { }` strategy to manually sync the threads along with it.
Mehrdad Afshari
+1  A: 

FileShare.None will only work if another process has also opened the file without allowing it to be shared for reads.

Programs such as Notepad and Visual Studio do not lock text files.

Jakob Christensen
Thanks Jakob, anyway to check whether a file is already opened by other thread/process?
George2
Hi Jakob, my situation is, a thread is serialization (using XML serialization) to the file, another reader thread is read from this file. I do not want the reader thread to operate on this file while XML serialization is in process, any ideas?
George2
How are you serializing? When serializing you must open the file exclusively (i.e. FileAccess.Write and FileShare.None).
Jakob Christensen
sorry I am wrong. what I said serialization is not 100% accurate in my situation. (continue)
George2
my situation is, one thread is copying file (using File.Move method), and another thread is read from the file. I do not want the reader thread to read a partial of the file while copy is in process(this is why I want to have exclusive open mode), does my code posted solve this issue?
George2
Yes, I think your code solves it. Files are locked while being written during a copy operation so your code will not be able to read from the files during the copy operation.
Jakob Christensen
+2  A: 

What you have done is correct.

If you need what are all files already opened, then there is a way to see by NtQuerySystemInformation

You may get idea from http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx

which gets all the files opened in a directory.. which can be extended to a single file whether opened or not...

lakshmanaraj
Thanks lakshmanaraj, my situation is, a thread is serialization (using XML serialization) to the file, another reader thread is read from this file. I do not want the reader thread to operate on this file while XML serialization is in process, any ideas?
George2
You may lock the file or do a mutex by setting a semaphore to operation
lakshmanaraj
file name is arbitrary so it is hard to lock. More details, I copy arbitrary files from remote machine to local machine using writer thread, and a reader thread will scan the folder and read information for new coming files
George2
(continued) my situation is, one thread is copying file (using File.Move method), and another thread is read from the file. I do not want the reader thread to read a partial of the file while copy is in process(this is why I want to have exclusive open mode), does my code posted solve this issue?
George2
Yes, Files are locked automatically while being written during a copy operation so your code will not be able to read from the files during the copy operation. Still you can check status(file) and struct stat->st_mode will give the share mode of the file whether it can be accessed or not.
lakshmanaraj
A: 

Test it by writing a simple console mode program that opens the file and then waits:

static void Main(string args[])
{
    using (FileStream f = File.Open("c:\\software\\code.txt", FileMode.Open, FileAccess.Read, FileShare.None))
    {
        Console.Write("File is open. Press Enter when done.");
        Console.ReadLine();
    }
}

Run that program from the command line (or another instance of Visual Studio), and then run your program. That way, you can play with different values for FileMode and FileShare to make sure that your program reacts correctly in all cases.

And, no, you don't have to check to see if the file is open first. Your code should throw an exception if the file is already open. So all you have to do is handle that exception.

Jim Mischel
Hi Jim, my situation is, one thread is copying file (using File.Move method), and another thread is read from the file. I do not want the reader thread to read a partial of the file while copy is in process(this is why I want to have exclusive open mode), does my code posted solve this issue?
George2
Yes, your code solves that issue. It will not open the file if File.Move is in the middle of copying it.
Jim Mischel