I cannot understand why I need to dispose the File.Create or wrap the creation within a using station before accessing the file and write to it. Why do I need to dispose that instances of Stream class that File.Create initialized, and have to create another Stream instance to write to it? Are they on a different thread, why?
Why can't creation, text-writing, and deletion share the same Stream? Perhaps I just do not understand Stream.
For example:
File.Create(...);
File.ReadLine(...); <-- The process cannot access the file ... because it is being used by another process
using (File.Create(...)) {};
File.ReadLine(...); <-- OK
See the Remarks section on the File.Create page on MSDN (emphasis mine):
The FileStream object created by this method has a default FileShare
value of None; no other process or code can access the created file
until the original file handle is closed.
Related
I ran into something interesting when using a StreamWriter with a FileStream to append text to an existing file in .NET 4.5 (haven't tried any older frameworks). I tried two ways, one worked and one didn't. I'm wondering what the difference between the two is.
Both methods contained the following code at the top
if (!File.Exists(filepath))
using (File.Create(filepath));
I have the creation in a using statement because I've found through personal experience that it's the best way to ensure that the application fully closes the file.
Non-Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
(new StreamWriter(f)).WriteLine("somestring");
With this method nothing ends up being appended to the file.
Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
using (StreamWriter s = new StreamWriter(f))
s.WriteLine("somestring");
I've done a bit of Googling, without quite knowing what to search for, and haven't found anything informative. So, why is it that the anonymous StreamWriter fails where the (non-anonymous? named?) StreamWriter works?
It sounds like you did not flush the stream.
http://msdn.microsoft.com/en-us/library/system.io.stream.flush.aspx
It looks like StreamWriter writes to a buffer before writing to the final destination, in this case, the file. You may also be able to set the AutoFlush property and not have to explicitly flush it.
http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush.aspx
To answer your question, when you use the "using" block, it calls dispose on the StreamWriter, which must in turn call Flush.
The difference between the two code snippets is the use of using. The using statement disposes the object at the end of the block.
A StreamWriter buffers data before writing it to the underlying stream. Disposing the StreamWriter flushes the buffer. If you don't flush the buffer, nothing gets written.
From MSDN:
You must call Close to ensure that all data is correctly written out to the underlying stream.
See also: When should I use “using” blocks in C#?
Is it true that this does not necessarily mean the stream has been disposed of by code - either in a using or by calling dispose.
The stream could have been closed outside of this code and this exception would still occur?
So I will make my comment an answer: Yes, a stream could just as well be closed from outside your code, so make sure you check for a System.ObjectDisposedException.
There are several occasions this could happen: imagine for example a stream associated with a network connection and the connection is suddenly interrupted. Depending on the implementation this could close the stream and throw that particular exception if the stream is accessed.
The stream could have been closed outside of this code and this exception would still occur?
Yes. For example - This can happen if you wrap a stream within another stream, and dispose of the "wrapper" stream. Many implementations dispose of the stream they are wrapping.
If you then try to write to the "wrapped" stream, you'll receive this error message.
either in a using or by calling dispose.
Also realize that, for objects which have a Close() method, such as Stream, Close and Dispose typically perform the same function. Closing a stream also disposes of it.
This error can also happen if the requestLengthDiskThreshold is smaller than the size of the file you are trying to upload/handle via the stream. This is defined in your web.config:
<httpRuntime maxRequestLength="512000" requestLengthDiskThreshold="512000" />
If you loook at the explanation for the 2nd parameter here:
https://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.requestlengthdiskthreshold(v=vs.110).aspx
you will see that it sets the input-stream buffering threshold (in kilobytes). The default value is 80KB so if you don't have this value set and you try, for example, to ajax upload the file bigger than 80KB you will get the System.ObjectDisposedException exception since the stream will be closed once the threshold limit is met.
In my case I'm setting the threshold to 500MB...
This question already has answers here:
File being used by another process after using File.Create()
(11 answers)
Closed 8 years ago.
I check to see if a file exists with
if(!File.Exists(myPath))
{
File.Create(myPath);
}
However, when I go to create a StreamReader with this newly created file, I get an error saying that
The process cannot access the file '[my file path here]' because it is being used by another process.
There isn't a File.Close(myPath) that I can call so that it is closed after being created, so how do I free this resource so that I can open it later in my program?
File.Create(string) returns an instance of the FileStream class. You can call the Stream.Close() method on this object in order to close it and release resources that it's using:
var myFile = File.Create(myPath);
myFile.Close();
However, since FileStream implements IDisposable, you can take advantage of the using statement (generally the preferred way of handling a situation like this). This will ensure that the stream is closed and disposed of properly when you're done with it:
using (var myFile = File.Create(myPath))
{
// interact with myFile here, it will be disposed automatically
}
The function returns a FileStream object. So you could use it's return value to open your StreamWriter or close it using the proper method of the object:
File.Create(myPath).Close();
File.Create returns a FileStream object that you can call Close() on.
The reason is because a FileStream is returned from your method to create a file. You should return the FileStream into a variable or call the close method directly from it after the File.Create.
It is a best practice to let the using block help you implement the IDispose pattern for a task like this. Perhaps what might work better would be:
if(!File.Exists(myPath)){
using(FileStream fs = File.Create(myPath))
using(StreamWriter writer = new StreamWriter(fs)){
// do your work here
}
}
File.WriteAllText(file,content)
create
write
close
File.WriteAllBytes-- type binary
:)
I'm writing an application that creates a "Catalog" of files, which can be attributed with other meta data files such as attachments and thumbnails.
I'm trying to abstract the interface to a catalog to the point where a consumer of a catalog does not need to know about the underlying file system used to store the files. So I've created an interface called IFileSystemAdaptor which is shown below.
public interface IFileSystemAdaptor:IDisposable
{
void WriteFileData(string fileName, Stream data);
Stream ReadFileData(string filename);
void DeleteFileData(string filename);
void ClearAllData();
void WriteMetaFileData(string filename, string path, Stream data);
Stream ReadMetaFileData(string filename, string path);
void DeleteMetaFileData(string filename, string path);
void ClearMetaFilesData(string filename);
}
Essentially my IFileSystemAdaptor interface exposes a flat list of files, that can also be associated with additional meta data files.
As you can see I'm using references to generic Stream objects to abstract the interface to a file's data. This way one implementation of a Catalog could return files from a hard disk, while another could return the data from a web server.
Now I'm trying to figure out how to keep my program from leaving streams open. Is there a rule of thumb for what members should close streams? Should the consumer of a stream close it, or should the member that original created the stream be responsible for closing it.
My Rules:
Should the consumer of a stream close it
If I return a stream from a method, the consumer is responsible. I'm giving it to you, It's your responsilibity.
If I accept a stream as a parameter in a method, I don't close it. When exiting the method, I don't know if the calling method still needs it. It's your stream, I'm just borrowing it, and I don't want to mess you up.
If I create a stream and pass it to another method, my method closes it (or tries to) when I am done with it. I don't know what you are going to do with it, but it's my stream, so I am responsible for it.
My spontaneous thought in this case is that the consumer should hold the responsibility for closing the streams. An IFileSystemAdaptor can't know when the consumer is done using the stream, so it also can't decide when to close it.
In effect the last object to use the stream should be responsible for closing it, and that is generally the caller.
Enjoy!
Using method: System.IO.File.Create()
After the file gets created, it still remains used by a process, and I can't delete it.
Any idea how I can better create the file, should be a 0byte file, and then somehow close and dispose?
JL,
You should wrap your call to .Create in a using statement so that the FileStream that .Create returns will be closed properly. IE:
using (File.Create("path")){...}
The Create method not only creates the file, it opens it and return a FileStream object that you can use to write to the file.
You have to close the file after yourself, otherwise it will not be closed before the garbage collector cleans up the FileStream object.
The easiest way is to simply close the file using the reference that the Create method returns:
File.Create(fileName).Close();
nikmd23 has the short answer, the long answer is: the FileStream that File.Create(...) is returning is not being deterministically disposed of, therefore it's file handle is not closed when you're trying to delete it.
As nikmd23 put it, wrapping your File.Create(...) call will with a using statement will make sure the stream is closed and disposed of:
using (FileStream fs = File.Create(path)) {
// do anything with the stream if need-be...
}
File.Delete(path); //after it's been disposed of.
The using(...) block is really just compiler-sugar for:
FileStream fs = File.Create(path);
try {
// do anything with the stream if need-be...
}
finally {
fs.Dispose();
}
File.Delete(path)
You should use nikmd23's answer in almost all cases. If you can't, because you need to pass the FileStream somewhere else, make sure to call the FileStream.Close method eventually. Preferably you would have the class that 'owns' the FileStream implement IDisposable itself, and close the stream in its Dispose method.
For more information on implementing IDisposable, refer to the MSDN documentation. Easier reading, and more up to date, is Joe Duffy's post on the subject.
using(FileStream f = File.Create(file_path))
{
// ... do something with file
f.Close();
}
The "f.Close();" line closing file immediately. If not close manually, Disposing may not close it.
See System.IO.File.Create(String) Method paramter and return value description
Parameters
path
Type: System.String
The path and name of the file to create.
Return Value
Type: System.IO.FileStream
A FileStream that provides read/write access to the file specified in path.
The FileStream return value is there for IO access to the created file. If you are not interested in writing (or reading) the newly created file, close the stream. That is what the using block is ensuring.