Read already opened file - c#

Is there a way to read binary data from a read-only file? I have an Excel worksheet, which might be opened in Excel but I want to open it for read purposes only.
I tried to do it this way:
using (FileStream fileStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read))
And I am getting
The process cannot access the file 'something.xlsx' because it is being used by another process.
Is there any way to achieve that?

Change this argument:
FileShare.Read
to this:
FileShare.ReadWrite
You are attempting to deny write access to the file, which is causing your issue as Excel already has it open for writing.

You can't open a file who are already open. Be careful to close your file after open it. And you should verify that you didn't use the file in another software (at the same time)...

Related

Is there a way I can allow a specific process to also read a file while FileStream is opened?

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.

Opening a file that's in use by another process

I've looked at several solutions to reading a file that's already in use by another process, but none of them seem to work for me.
The file I'm trying to read is an XML file that contains configuration settings that I need to extract.
Here's what I have tried:
using (var stream = File.Open("\\\\2008r2\\c$\\ProgramData\\location\\siteConfig.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(stream))
{
// Actions you perform on the reader.
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
This seems to work for just about everyone else, I don't know what I'm doing wrong! Is my file locked in a different manner and cannot be accessed even to read?
Help much appreciated!
Dave
From your comment, the original process has opened the file with FileShare.None. From MSDN:
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.
The original process has an exclusive lock on it so you won't be able to read from it unless the FileShare enumeration is changed from None or the file is closed.

Why can a file which is open in a stream not be renamed?

With the following piece of code, i read a file and keep the stream open.
static void Main(string[] args)
{
FileStream fileStream = new FileStream(#"C:\temp\test1.txt", FileMode.Open);
Console.ReadLine();
}
If i now try to rename this file, the message "File in use" is shown.
It looks like the rename of a file should be possible(on os level), even if it is in use: Why does rename a loaded .net assembly work?
Why can't a file be renamed when it is loaded in a stream by .net?
About assemblies, .NET should open the assembly using something like FileShare.ReadWrite so, even if it's loaded into the domain, any other process can write or rename the whole file.
AFAIK, .NET doesn't have a managed FileShare enum value for allowing or disallowing renaming the file share (something like FileShare.Rename), but Win32 should have thus assembly loading would be creating the file stream with a mask like FileShare.ReadWrite | FileShare.Rename (FileShare.Delete includes renaming but also removing the whole file...).
For demonstrating this, I've tried the following code:
FileStream a = File.Open(#"C:\blah.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
a.Dispose();
While the file stream was opened and until it's disposed, I couldn't delete the whole file but I could rename it.
Note that assemblies are loaded into the AppDomain when they're needed, meaning that maybe you can write, delete or rename an assembly because it's not loaded yet.
Try to delete an assembly already loaded into the AppDomain: you can't (I've tried myself just now, the test code runs in a console app and I couldn't remove the executable while running it). Now try to rename it: it works.
Summary
It's all about how a file is opened and which file mask configuration was used when the file stream was opened: this is why your file can't be renamed but you can rename an already loaded assembly.
Modify your code like the next one and you'll be able to rename the whole file (even delete it!):
FileStream fileStream = File.Open(#"C:\temp\test1.txt", FileMode.Open, FileShare.ReadWrite | FileShare.Delete);
Console.ReadLine();
When you create a FileStream you don't load it's data to the memory.
when you are seeking the stream, the file content is still read from the disk - a good thing to do when you need to read big files.
If all you want to do is to load the whole content to memory you can use File.ReadAllBytes.
You can read more about it here: http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx.
Note: If you want to use a stream and not a byte array, you can use MemoryStream and pass the read file content to it.

How to open a StreamReader in ShareDenyWrite mode?

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.

Cannot write to file while it is opened in MS Excel

I am writing to the text file some data. I am using this code:
using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (TextWriter tw = new StreamWriter(fs))
{
tw.WriteLine("sample_data");
}
}
When file is opened by notepad my app can write into it. When this file is opened by MS Excel I get following error: The process cannot access the file myfile.csv because it is being used by another process. What can cause this situation and how can I solve this problem?
Notepad opens the file, reads in the entire contents and then closes the file. You can even delete the file that is open in notepad.
Excel on the other hand keeps the file open as long as it is displayed. There are some special sharing tools that can be enabled in Excel for excel format files. In that case I assume that it is opened non-exlusively. Otherwise Excel opens the file exclusively and keeps it open.
It doesn't matter that you specify a share option when opening, if the file is already opened by someone else in exclusive mode.
Excel will lock the file when it is open which prevents interaction with the file. One way I worked around this is that I wrote code to scan for excel processes on the local machine and would kill those processes before accessing a file that was open with excel. You could determine if a file is locked by looking at How to check for file lock? and then running the process killing code in the exception handler.
Open the csv file using OleDB and use INSERT and/or UPDATE statements.

Categories

Resources