open file in exclusive mode in C#

65

Solution 1

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();
}

Solution 2

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.

Solution 3

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...

Solution 4

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.

Solution 5

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.

Share:
65
Ali Bagheri
Author by

Ali Bagheri

Updated on July 09, 2022

Comments

  • Ali Bagheri
    Ali Bagheri almost 2 years

    I have a table.

    create table tb(
      userid int,
      nodes jsonb)
    

    nodes sample:

    {
     "weight": [{"date":"<date>", value: 50}, {"date":"<date>", value: 60}],
     "height": [{"date":"<date>", value: 170}, {"date":"<date>", value: 172}],
    }
    

    I want to change the weight of a date in the list of weights.

    Or enter a new value in the height list on a specific date. What should I do?

    I wrote this. but it is add a new item only.

    INSERT INTO tb (UserId, Nodes)
    values (1, '{"weight": [{"value":"50","date":"2021-07-24 18:17:33.000"}]}')
    ON CONFLICT (UserId) DO UPDATE
        SET Nodes = jsonb_set(tb.Nodes, '{"weight"}',
                              tb.Nodes->'weight' || '{"value":"50","date":"2021-07-24 18:17:43.000"}');
    

    I need to edit a value for a specific date.

    • Bergi
      Bergi almost 3 years
      Have you considered normalising your database schema instead of storing JSON?
    • Bergi
      Bergi almost 3 years
      "enter a new value in the height list on a specific date" - your current code does that already, no?
    • Ali Bagheri
      Ali Bagheri almost 3 years
      No, really, this is not just my data. I wrote this for simplicity. Each user has specific information that is not the same, but all have a date field.
    • Ali Bagheri
      Ali Bagheri almost 3 years
      No, I have to search between dates and edit any that have a specific date, regardless of the time
    • Bergi
      Bergi almost 3 years
      You mean you want to append a new value for a date, but if an entry with that date already exists, it should be overwritten? I.e. you don't know when you need to update vs when you need to insert? Because the insertion part already works in the code you have.
    • Bergi
      Bergi almost 3 years
      Do you care about the order in that array?
  • George2
    George2 about 15 years
    Thanks Jakob, anyway to check whether a file is already opened by other thread/process?
  • George2
    George2 about 15 years
    Thanks Mehrdad, anyway to check whether a file is already opened by other thread/process?
  • George2
    George2 about 15 years
    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)?
  • mmx
    mmx about 15 years
    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.
  • George2
    George2 about 15 years
    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
    George2 about 15 years
    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?
  • mmx
    mmx about 15 years
    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.
  • Cerebrus
    Cerebrus about 15 years
    No, I don't think there is... except by catching the IOException in the code that tries to subsequently read the file.
  • George2
    George2 about 15 years
    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
    George2 about 15 years
    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
    George2 about 15 years
    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?
  • mmx
    mmx about 15 years
    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: msdn.microsoft.com/en-us/library/…
  • George2
    George2 about 15 years
    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
  • Jakob Christensen
    Jakob Christensen about 15 years
    How are you serializing? When serializing you must open the file exclusively (i.e. FileAccess.Write and FileShare.None).
  • lakshmanaraj
    lakshmanaraj about 15 years
    You may lock the file or do a mutex by setting a semaphore to operation
  • George2
    George2 about 15 years
    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
    George2 about 15 years
    File is very big so using RDBMS is not very efficient. (continued)
  • George2
    George2 about 15 years
    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
    George2 about 15 years
    sorry I am wrong. what I said serialization is not 100% accurate in my situation. (continue)
  • George2
    George2 about 15 years
    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
    George2 about 15 years
    (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
    George2 about 15 years
    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?
  • Jakob Christensen
    Jakob Christensen about 15 years
    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.
  • mmx
    mmx about 15 years
    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.
  • Jim Mischel
    Jim Mischel about 15 years
    Yes, your code solves that issue. It will not open the file if File.Move is in the middle of copying it.
  • lakshmanaraj
    lakshmanaraj about 15 years
    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.
  • Admin
    Admin over 11 years
    Jim, how do I know if any(!) program is opening it? Either notepad or something else. Or how do I know if it's being copied right now?
  • Jim Mischel
    Jim Mischel over 11 years
    @Grienders: If the call to File.Open in this code example fails with an access violation exception, then the file is currently open from another program. You can't tell, however, if somebody is using Notepad to view the file, because Notepad opens the file, reads it into memory, and closes the file. If the file is currently being copied, the program doing the copy will have it open.