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#?
Related
This question already has answers here:
Cannot write to file after reading
(5 answers)
Closed 3 years ago.
This question stems from this other thread: How to lock a file with C#?
Basically let's say you want to lock a JSON file, read it, then write to it afterward, and finally unlock it. You can lock the file using the answers from the other question.
However I'm having trouble where this is allowing me to read the file, but not write to it afterward without first unlocking the file. That is, the recommended method, which seems to be fairly well-respected, is locking the same thread out of its own resource.
Example:
using (var fs = new FileStream(GetJsonPath(), FileMode.Open, FileAccess.ReadWrite,
FileShare.None))
{
SomeDtoType dto;
using (StreamReader reader = new StreamReader(fs))
{
dto = ((SomeDtoType)(new JsonSerializer()).Deserialize(reader,
typeof(SomeDtoType)));
}
// Make changes to the DTO.....
using (StreamWriter writer = new StreamWriter(fs))
{
new JsonSerializer().Serialize(writer, dto);
}
}
The using line that creates the StreamWriter throws the following exception:
Stream was not writable.
Now one thing that comes to mind is the value of FileShare.None. The problem here is that that particular enum is evidently setting lock permissions for more than just external processes.
How can you lock external threads/processes out of changing/deleting the file, yet allow your own to make these two subsequent read/write accesses?
EDIT:
Evidently moving everything into the using block for the StreamReader, then setting fs.Position to 0 between the read and the write kind of fixes the issue. The fs.Position part is fine, but having to move the write logic into the using block for the StreamReader, just so they can both use the same FileStream lock, seems a tad odd...
StreamReader closes the stream if you don't use ctor overload and instruct it don't do that:
using (StreamReader reader = new StreamReader(fs, Encoding.UTF8, true, 4096, leaveOpen:true))
There is no finalizer in StreamReader, you can move it out using block and keep as undisposed, however I'd recommend explicitly control the lifetime and behavior.
Another issue is that you'll append to the file. If you want to override a content you need to reset it before you write to it:
fs.SetLength(0);
I was searching in StackOverflow about try-finally and using blocks and what are the best practices on using them.
I read in a comment here that if your application is terminated abruptly by killing the process, a finally block will not get executed.
I was wondering, does the same apply to the using blocks? Will for example a stream get closed if a Environment.exit() call occurs inside the using block?:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
Environment.exit();
}
As a second thought on it, and knowing that CLR Garbage Collector will probably take care of the stream objects if not closed properly in the program calls, is it considered necessary to close a stream in code, if the program gets terminated for sure after the completion of the stream usage?
For example, is there any practical difference between:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
}
Environment.exit();
And:
//....
FileStream fsSource1 = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
//Use the stream here
Environment.exit();
Or even the example mentioned before?
It shouldn't make a difference in the specific case of FileStream, modulo a tricky corner case when you used its BeginWrite() method. Its finalizer attempts to complete writing any unwritten data still present in its internal buffer. This is however not generally true, it will make a difference if you use StreamWriter for example.
What you are leaving up to the .NET Framework to decide is whether you truly meant to jerk the floor mat and seize writing the file. Or whether it should make a last-gasp attempt to flush any unwritten data. The outcome in the case of StreamWriter will tend to be an unpleasant one, non-zero odds that something is going to fall over when it tries to read a half-written file.
Always be explicit, if you want to make sure this does not happen then it is up to you to ensure that you properly called the Close() or Dispose() method. Or delete the file.
I have two programs that work together. To coordinate their operations I use a small settings file. This setting file contains two words separated by a ';'. So in the one program I repeatedly read the words in the file using a while loop. By repeatedly I mean once every second. The loop only terminates when the program terminates; when the user turns off the pc.
But with each iteration of the loop the program size in memory increases until the program throws an OutOfMemory exception. I have tried two different methods of reading the files but both causes the program to 'grow' in memory.
FileStream FS = new FileStream("br.stat", FileMode.Open);
StreamReader SR = new StreamReader(FS);
string s = SR.ReadToEnd();
FS.Dispose();
SR.Dispose();
and
string S = File.ReadAllText("br.stat");
Is there a way to read a file repeatedly with out this happening?
Thanks.
the problem is the design, more so than the implementation. You only need to read from the file once when the app starts and again when the file changes. You can use FileSystemWatcher to detect changes to the file and reload the settings.
This uses drastically less resources than reading the file indefinitely.
also, you'll want to take advantage of the using keyword to ensure you properly dispose of the file stream and reader. In fact I would simplify and just use File.ReadAllText(filename).
I think you're doing it wrong. Realistically there is no need to read the file every iteration unless its changed.
Instead it would be better to use a FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.changed(v=vs.85).aspx to read the values and change your control values.
You should also use the following to circumvent your memory leak issues
using (var FS = new FileStream("br.stat", FileMode.Open))
{
using (var SR = new StreamReader(FS))
{
var s = SR.ReadToEnd();
}
}
I would recomend you look at using an using statement
File and Font are examples of managed types that access unmanaged
resources (in this case file handles and device contexts). There are
many other kinds of unmanaged resources and class library types that
encapsulate them. All such types must implement the IDisposable
interface.
As a rule, when you use an IDisposable object, you should declare and
instantiate it in a using statement. The using statement calls the
Dispose method on the object in the correct way, and (when you use it
as shown earlier) it also causes the object itself to go out of scope
as soon as Dispose is called. Within the using block, the object is
read-only and cannot be modified or reassigned.
so something like
using (FileStream FS = new FileStream("br.stat", FileMode.Open))
using (StreamReader SR = new StreamReader(FS))
{
string s = SR.ReadToEnd();
}
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.
A few days ago I posted some code like this:
StreamWriter writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close();
Response.End();
I was told that instead I should wrap StreamWriter in a using block in case of exceptions. Such a change would make it look like this:
using(StreamWriter writer = new StreamWriter(Response.OutputStream))
{
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close(); //not necessary I think... end of using block should close writer
}
Response.End();
I am not sure why this is a valuable change. If an exception occurred without the using block, the writer and response would still be cleaned up, right? What does the using block gain me?
Nope the stream would stay open in the first example, since the error would negate the closing of it.
The using operator forces the calling of Dispose() which is supposed to clean the object up and close all open connections when it exits the block.
I'm going to give the dissenting opinion. The answer to the specific question "Is it necessary to wrap StreamWriter in a using block?" is actually No. In fact, you should not call Dispose on a StreamWriter, because its Dispose is badly designed and does the wrong thing.
The problem with StreamWriter is that, when you Dispose it, it Disposes the underlying stream. If you created the StreamWriter with a filename, and it created its own FileStream internally, then this behavior would be totally appropriate. But if, as here, you created the StreamWriter with an existing stream, then this behavior is absolutely The Wrong Thing(tm). But it does it anyway.
Code like this won't work:
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream)) { ... }
stream.Position = 0;
using (var reader = new StreamReader(stream)) { ... }
because when the StreamWriter's using block Disposes the StreamWriter, that will in turn throw away the stream. So when you try to read from the stream, you get an ObjectDisposedException.
StreamWriter is a horrible violation of the "clean up your own mess" rule. It tries to clean up someone else's mess, whether they wanted it to or not.
(Imagine if you tried this in real life. Try explaining to the cops why you broke into someone else's house and started throwing all their stuff into the trash...)
For that reason, I consider StreamWriter (and StreamReader, which does the same thing) to be among the very few classes where "if it implements IDisposable, you should call Dispose" is wrong. Never call Dispose on a StreamWriter that was created on an existing stream. Call Flush() instead.
Then just make sure you clean up the Stream when you should. (As Joe pointed out, ASP.NET disposes the Response.OutputStream for you, so you don't need to worry about it here.)
Warning: if you don't Dispose the StreamWriter, then you do need to call Flush() when you're done writing. Otherwise you could have data still being buffered in memory that never makes it to the output stream.
My rule for StreamReader is, pretend it doesn't implement IDisposable. Just let it go when you're done.
My rule for StreamWriter is, call Flush where you otherwise would have called Dispose. (This means you have to use a try..finally instead of a using.)
If an exception occurs without the using block and kills the program, you will be left with openconnections. The using block will always close the connection for you, similiar to if you were to use try{}catch{}finally{}
Eventually, the writer will be cleaned up. When this happens is up to the garbage collector, who will notice that the Dispose for the command has not been called, and invoke it. Of course, the GC may not run for minutes, hours or days depending on the situation. If the writer is holding an exclusive lock on say, a file, no other process will be able to open it, even though you're long finished.
The using block ensures the Dispose call is always made, and hence that the Close is always called, regardless of what control flow occurs.
Wrapping the StreamWriter in a using block is pretty much equivalent of the following code:
StreamWriter writer;
try
{
writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
}
catch
{
throw;
}
finally
{
if (writer != null)
{
writer.Close();
}
}
While you could very well write this code yourself, it is so much easier to just put it in a using block.
In my opinion it's necessary to wrap any class that implements IDisposable in a using block. The fact that a class implements IDisposable means that the class has resources that need to be cleaned up.
My rule of thumb is, if I see Dispose listed in intellisense, I wrap it in a using block.
the using block calls dispose() when it ends. It's just a handy way of ensuring that resources are cleaned up in a timely manner.
In almost every case, if a class implements IDisposable, and if you're creating an instance of that class, then you need the using block.
While it's good practice to always dipose disposable classes such as StreamWriter, as others point out, in this case it doesn't matter.
Response.OutputStream will be disposed by the ASP.NET infrastructure when it's finished processing your request.
StreamWriter assumes it "owns" a Stream passed to the constructor, and will therefore Close the stream when it's disposed. But in the sample you provide, the stream was instantiated outside your code, so there will be another owner who is responsible for the clean-up.