I want to read the content of a file which is opened (and locked?) by a other process.
I tried it with File.ReadAllText() and with new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read)) but both methods trigger a IOException.
For example I can open the file with Notepad++ and the content is shown so I think it must be possible too with c#.
You need to use the FileStream constructor overload that takes a FileShare argument. And pass FileShare.ReadWrite. You can only open the file if you permit write access since the other program already acquired that right. Otherwise the reason that your attempts failed so far, they used FileShare.Read. Can't work, you cannot deny write access because the other program already got that.
Dealing with the program writing to the file while you are reading it is entirely up to you. Results can be quite random. Anything is possible, but in general for a log file you'll get a partially written last line that's trailing behind the actual output of the program, some of which is still in the program's file buffer. A buffer size of 4096 bytes is a common choice.
Related
My program opens a file for reading purposes and does not let other programs access its contents. This is exactly what I want to do, except another specific process also needs to read the file. I do not manage this process, so that would be ideal if I could define it by its name or PID.
What I have done:
FileStream fileStream = new FileStream(FILE, FileMode.Open, FileAccess.Read, FileShare.None);
The problem with what I did, as previously stated, was it won't allow the other process to read from it. I know I could just have it close the FileStream, use File. Read, or change FileShare, but I only one my process and the other process to read the file.
I use StreamWriter to write logs. I sometimes open this log file with Excel while my program is running.
I find that Excel lock this file so I get IOException when my program try to write logs.
Can I take out the lock which was set by other process?
I know I can lock the file while my program is running but it cause similar problem when I open it with Excel.
Note that I won't write anything with the other process.
using(var sw = new StreamWriter(
new FileStream(filename, FileMode.Append, FileAccess.Write), Encoding.GetEncoding("UTF-16")))
No, you can't "take ownership of lock on file" (unless other application is designed o allow such access).
The other application must be opening file with particular share mode to allow your to simultaneously access the file.
Note that most application don't open files in such mode due to problems keeping state consistent.
.Net way of specifying share mode - use desired value from FileShare enumeration when opening files. There are multiple samples and discussion about it on SO like C# multiple instances of program reading from same file.
I have a process where I am writing byte array to a file (StorageFile). The process runs in periodic intervals and during the same time I need to read from the beginning of the file in another process. The two processes are in different classes. When I start reading the file, the write operation fails with access denied error.
Here the file is a StorageFile inside the app folder.
The write method calls:
IRandomAccessStream randomStream = await targetFile.OpenAsync(FileAccessMode.ReadWrite);
Stream stream = randomStream.AsStreamForWrite();
The read method calls:
IRandomAccessStream randomStream = await targetFile.OpenAsync(FileAccessMode.Read);
Stream stream = randomStream.AsStreamForRead();
Both operations take place simultaneously from different methods and it results in an access denied error. Seems I can use the read/write inside the same method while opening for write. But how to do that from different methods??
Do we have anything similar to the earlier System.IO.FileShare so that I can explicitly say that this file needs to be accessed from another location in the same app?
Besides switching to a database type setup, I would suggest buffering your writes to an array and writing them in chunks based on the buffer filling and/or certain about of time elapsed. Unless you need the latest and greatest performance down to the millisecond, I doubt people will notice a performance impact. You will have to play with the buffer size to make sure you give your reader enough time to actually read the file.
On the reader side, you could implement a FileSystemWatcher object on the file.
I have a program that logs it's progress and other data to an XML file. I want to be able to open this XML file without blocking out the writer program (not a .NET program, and I have no control over it), and to read the XML as it comes, waiting for more when it is all processed, until the EOF is received.
How can this be achieved in C#?
Note that there are 2 problems:
Keeping a reading stream open without blocking the other process.
Knowing when there is more input and waiting when there isn't.
If I needed to do this I would do something like the following:
Use a FileSystemWatcher to get notified when the file changes. Then just read the file and parse the XML as you require.
I would go down this route as it will be difficult to read the stream as and when the external application writes to the file.
I did soemthing similar in past yielding in an OS program called Tailf.
Just check the code if you want to do it yourself, or grab all from it, it should almost work for you as well, a part the fact I just care about text files.
You can open a file stream without locking it by passing in the following flags:
new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
As far as waiting for the "EOF", if the other program is only writing data intermittently, you may have to put some sort of heuristics into your progress (ie. stop peeking for new data only if there's nothing new for X minutes).
How do i open a StreamReader with FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE?
Same question, slightly expanded
How do i open a StreamReader so that i can read an encoded text file, with sharing options so that another process can read the file?
How do i open a StreamReader so that i can read an encoded text file, with sharing options so that another process can modify the file while i'm reading it?
How do i open a StreamReader so that i can read an encoded text file, with sharing options so that another process can delete the file while i'm reading it?
Same question, slightly more expanded
In the .NET Framework class library there is a class called StreamReader. It is the only class designed to read "text", which is why it descends from the abstract base TextReader class. The TextReader/StreamReader allows you to specify the encoding used by the file you are trying to open, and can decode the file for you, returning Strings of text.
Once i've opened a file with the StreamReader:
var sr = new StreamReader(path);
The file is locked, with other processes unable to modify or delete the file. What i need is the equivalent of a FileStream class's FileShare enumeration:
None: Declines sharing of the current file. Any request to open the file (by this process or another process) will fail until the file is closed.
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, even if this flag is specified, additional permissions might still be needed to access the file.
Write: Allows subsequent opening of the file for writing. If this flag is not specified, any request to open the file for writing (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.
ReadWrite:Allows subsequent opening of the file for reading or writing. If this flag is not specified, any request to open the file for reading or writing (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.
Delete: Allows subsequent deleting of a file.
Except that, for obvious reasons, i cannot use a FileStream - have to use a StreamReader.
How can i open a StreamReader with FileShare.ReadWrite | FileShare.Delete?
StreamReader has a constructor that can take a stream. So instead of using the constructor that takes a string path, first create a FileStream with the options that you want, then pass that FileStream to the StreamReader constructor.
How can i open a StreamReader with FileShare.ReadWrite | FileShare.Delete ?
When you have solved the problem for a Stream, the Reader is easy:
var fs = new FileStream(fileName, FileMode.Open, FileShare.ReadWrite|FileShare.Delete);
var sr = new StreamReader(fs);
And of course that should be wrapped in a using() { } block.