I want to open a file and block others from writing to it, but allow them to read it. Then after some calculations, I want to block reads as well while I write to it, so no process gets a partially written file.
However, while it seems that I can specify creation of a FileStream with either FileShare.Read or FileShare.None, I can't seem to find a way to start out with FileShare.Read and then change to FileShare.None.
The reason I don't want to create a new FileStream (with FileShare.None) is because I don't want any changes to be made to the file while I shift from the old FileStream to the new one.
using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
...
}
Related
I'm creating files in C# from InputStreams and writing them to a public shared folder. I can't have someone else reading the file before I've set it's LastWriteTime property. I'm using the following code:
// Write file to disk
using (var fileStream = File.Create(fileName))
{
webStream.CopyTo(fileStream);
}
File.SetLastWriteTimeUtc(path, timestamp);
A situation could occur where someone else reads the file before File.SetLastWriteTimeUtc() is called. How do I prevent this?
You'll have to set the correct sharing options when creating the filestream:
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)
Your last instruction should also be inside the using statement, as using guarantees that the file is closed when outside of it.
I have a file that gets GBs of data written to it over time (looping once it reaches the end). I would like to create the file ahead of time and preset the storage so that the required storage is never taken up by other downloads during the writing to the file. This is done using visual studio 2012 in C#.
I have tried:
if (fileSizeRequirement or fileName is changed) //if filePath or file size is changed
{
//Open or create the file, set the file to size requirement, close the filestream
fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
fileStream.SetLength((long)fileSizeRequirement);
fileStream.Close();
}
1) Is this an appropriate way to "preallocate" space for a folder?
2) Will the SetLength require a seek to the beginning after setting the length or does the position in the folder stay at the beginning?
3) What is the correct way to achieve file preallocation of storage space?
Thanks ahead of time and I appreciate any suggestions.
Using SetLength is a common approach although I'd generally use a using statement here.
using(var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
fileStream.SetLength((long)fileSizeRequirement);
}
Calling fileStream.Position straight after SetLength yields 0 so you shouldn't need to seek to the beginning.
To read a file that's already opened by another process, you usually do something like this.
var outStream = new FileStream(fileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
Is there a way to achieve the opposite effect? In other words, have a program exclusively own the file and make sure that no other processes can read the file until the stream has been closed?
Use FileShare with option None this will give you
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.
You can read more about it here
Your Code should be :
using (Stream iStream = File.Open("c:\\myFile.txt", FileMode.Open,
FileAccess.Read, FileShare.None))
{
//your code here
}
Is there any performance or any kind of effect on OS's file system permission between the codes below:
FileStream fs = new FileStream(#"file.dat", FileMode.Create, FileAccess.Write);
// and
FileStream fs = File.Create(#"file.dat");
PS: except the usage of a static function issue.
According to reflector, File.Create(path) is just:
new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.None);
and new FileStream(#"file.dat", FileMode.Create, FileAccess.Write) also gets the 4096 buffer - so no, it is just the FileAccess.ReadWrite which is different.
And I don't think FileAccess.Write is much better than FileAccess.ReadWrite because they both locks the file - but I may be wrong.
to comment: because FileShare is set to None and it is write access you want they properly (=I don't know for sure) ain't much of a difference. However, if you wanted Read access the new FileStream(path, mode, access) approach is different because FileShare is set to Read as a default. However, in this case you want to create a file, and therefore it does not make much sense to only read ;-)
If I recall correctly, File.Create("file.dat") just wraps a call to new FileStream("file.dat", FileMode.Create, FileAccess.ReadWrite).
I'd like to open the same file for both reading and writing. The file pointer should be independent. So a read operation should not move the write position and vice versa.
Currently, I'm using this code:
FileStream fileWrite = File.Open (path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
FileStream fileRead = File.Open (path, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
StreamWriter _Writer = new StreamWriter (fileWrite, new ASCIIEncoding ());
StreamReader _Reader = new StreamReader (fileRead, new ASCIIEncoding ());
But that leads to an IOException: "The process cannot access the file because it is being used by another process"
I think I just figured it out myself. In the second File.Open, we're trying to deny other applications write access by specifying FileShare.Read. Instead, we need to allow the first stream to write to the file:
FileStream fileRead = File.Open (path, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
That's inherently correct, as the reading stream should not care about other people writing to the file. At least I don't get an exception anymore.
I don't have a C# at hand, so I cannot test it.
Can't you just use FileAccess.ReadWrite instead of FileAccess.Read?
Edit: The answer is no. You need to use FileShare to do it.