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).
Related
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))
{
...
}
This is updated question, there used to be a bug in my code
I would like to be able to send chunks of data over to the client.
Anything will be appreciated.
Is there a way to provide to asp.net core more control to how it streams the data.
I am worried how the below code scales.
Could someone please advise how to go streaming data through a web api in asp.net core?
The answer that was provided and the code below works. I am not sure how it scales though?
Is it possible to retrieve chunks of data and write them to the request, with only getting the chunks into memory. So i would be able to download very large files.
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return File(System.IO.File.OpenRead(filePath), "audio/mpeg");
}
Applying the FileStream approach - as already mentioned - use the FileStream constructor that accepts a bufferSize argument, which specifies the amount of bytes being read into memory.
(You can overrule the default value (4096) to fit your environment.)
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize);
bufferSize:
A positive System.Int32 value greater than 0 indicating
the buffer size.
The default buffer size is 4096.
public IActionResult GetFile()
{
var filePath = #"c:\temp\file.mpg"; // Your path to the audio file.
var bufferSize = 1024;
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize);
return File(fileStream, "audio/mpeg");
}
Note that there's no need to dispose the fileStream; the File method takes care of this.
To clarify:
When passing in a FileStream, its content is being read in chunks (matching the configured buffersize).
Concrete, this means that its Read method (int Read (byte[] array, int offset, int count)) gets executed repeatedly untill all bytes have been read, ensuring that no more than the given number of bytes are stored in memory.
So the scalability is within the less memory usage, as memory is a resource that can come under pressure if the size of the file is high, especially in combination with a high read frequency (of this or of other files)
which might cause out of memory problems.
Posting as a community wiki, since it doesn't technically answer the question, but suggested code won't work as a comment.
You can return a stream directly from FileResult, so there's no need to manually read from it. In fact, your code doesn't actually "stream", since you're basically reading the whole stream into memory, and then returning the byte[] at the end. Instead, just do:
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return File(fileStream, "audio/mpeg");
}
Or even simpler, just return the file path, and let FileResult handle it completely:
return File(System.IO.File.OpenRead(filePath), "audio/mpeg");
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
}
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.