Maybe it is a trival question, but it's bothering me. And don't shout laud if it is a duplicate - I tried to search, but there are so many questions regarding using that it was hard for me to find the answer.
I've a code like this:
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
using (StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("example.txt", FileMode.Create, ISF)))
writeFile.WriteLine("Example");
And my questions are: What happens to my created IsolatedStorageFileStream, when StreamWriter is disposed, while leaving using? Will it be also disposed?
Is there any difference in comparison to this code:
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
using (IsolatedStorageFileStream stream = ISF.CreateFile("example.txt"))
using (StreamWriter writeFile = new StreamWriter(stream))
writeFile.WriteLine("Example");
Thanks in advance.
You have a constructor for StreamWriter (NET Framework 4.5 only) that allows specifying the leaveOpen boolean that defines whether your instance takes ownership of the underlying stream or not.
If not specified (as in your example, or for previous versions of the framework), by default it's false, so closing (or disposing) the instance closes the underlying stream.
Unless you set the leaveOpen parameter to true, the StreamWriter
object calls Dispose() on the provided Stream object when
StreamWriter.Dispose is called.
So there is no difference between both pieces of code you provided.
Once it leaves the using block, Dispose is called.
using Statement (C# Reference)
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.
The using statement ensures that Dispose is called even if an
exception occurs while you are calling methods on the object.
Your stream remains open even though the stream writer is disposed of. You could, for example, open another stream writer and continue writing to the stream.
Use {} always! It makes the intention of your code a lot better.
Your code looks like:
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
using (StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("example.txt", FileMode.Create, ISF)))
{
writeFile.WriteLine("Example");
}
}
You can then see that the StreamWriter is executed in the context of the ISF. If I understand the ISF correctly, the ISF should not be closed when the Streamwriter closes the file. And you could open another File in the ISF Block.
Related
How do I manage closing StreamReader and StreamWriter which are using the same underlying stream?
var stream = /*...*/;
var reader = new StreamReader(stream);
var writer = new StreamWRiter(stream);
I know that I could simply ignore closing the reader/writer and just close the underlying stream. However, that seems a bit of a hack, since it is based on the assumption that the reader/writer doesn't have anything to dispose (which might not be the case in the future).
I know this have been solved in .NET 4.5 with an extra constructor argument, but until .NET 4.5 is released, how do I solve it in a proper way?
Make sure you Flush() the writer first.
And then just Dispose or Close the 2 decorators and the stream (nested usings are OK).
I'm using System.IO.File.Create to create a file. I'm not writing to it with a stream writer, just creating it.
I get a server error in the front end when the application tries to open the newly created file - that the file is in use. Garbage collection then seems to come along and a few minutes later all is OK.
Now I know if I was using Streamwriter I would have to close it. Does the same apply to creating?
I've read that opening a stream writer to the file then immediately closing it will fix this, but it seems messy. Is there a simpler way?
Try this:
System.IO.File.Create(FullFName).Close();
File.Create returns a FileStream. You should use it like this:
using (FileStream fs = File.Create(path))
{
//you can use the filstream here to put stuff in the file if you want to
}
Creating the file opens a FileStream to it, hence, locking it (File.Create returns the FileStream).
You must close this stream in order to access the file. This is best done with a using statement:
using(FileStream fs = File.Create(path))
{
}
When using File.Create you get a FileStream returned. Until you either close the stream or until the FileStream object is disposed (by the garbage collector's finaliser) it will remain open and locked.
FileStream implements IDisposable so you can do the following:
using(FileStream fs = File.Create(filename))
{
// Do stuff like write to the file
}
The using statement is "syntactic sugar" and causes the compiler to generate code that is functionally equivalent to:
FileStream fs = File.Create(filename)
try
{
// Do stuff like write to the file
}
finally
{
fs.Dispose();
}
The Dispose method calls Close internally.
I was using:
System.IO.File.Create(sFullFileName);
The above .Create method was not closing the file
I now use:
System.IO.File.WriteAllText(sFullFileName, "Uploading");
This method creates and closes the file (note: I put a string "Uploading" in the file, but i'm sure string.Empty will also work.
The Create method will return a file handle. The file handle should be closed before re-using the file. Please see details in the MSDN article File.Create Method (String).
Summary:
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.
I am writting a small app to export and import data from database using .NET DataSets and XML and as part of that I am doing the following.
StreamWriter sw = new StreamWriter(file);
sw.Write(xml.OuterXml);
sw.Close();
The problem is that the close method closes the FileStream (file parameter passed to constructor) but doesn't release the file lock. The file is one that the program I have written creates so I know nothing else is locking it.
Is there something I am doing wrong or is this a windows bug?
EDIT
Yes 'file' is a FileStream object and I naively assumed that calling close() on the stream that wraps the files stream would also cleanup and dispose the underlying file stream by calling the FileStream.close method. But i'm not sure about that any more.
Wrapping this in a using block still has the same effect.
One extra note is that the filestream object is created in a different method but that shouldn't make any difference
Try using this instead:
using (StreamWriter sw = new StreamWriter(file))
sw.Write(xml.OuterXml);
(or try to call sw.Dispose() manually)
Would it help to wrap the file stream in a using or simply use the overloaded method for creating the stream writer:
using (FileStream fs = new FileStream("path", FileMode.Append))
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(xml.OuterXml);
sw.Close();
}
or:
using (StreamWriter sw = new StreamWriter("path"))
{
sw.Write(xml.OuterXml);
sw.Close();
}
I suspect the problem is in the code creating or using the FileStream. Perhaps you could elaborate on how you use the FileStream object you create.
This question already has answers here:
Can you keep a StreamReader from disposing the underlying stream?
(9 answers)
Closed 7 years ago.
I need to read a stream two times, from start to end.
But the following code throws an ObjectDisposedException: Cannot access a closed file exception.
string fileToReadPath = #"<path here>";
using (FileStream fs = new FileStream(fileToReadPath, FileMode.Open))
{
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
fs.Seek(0, SeekOrigin.Begin); // ObjectDisposedException thrown.
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
Why is it happening? What is really disposed? And why manipulating StreamReader affects the associated stream in this way? Isn't it logical to expect that a seekable stream can be read several times, including by several StreamReaders?
This happens because the StreamReader takes over 'ownership' of the stream. In other words, it makes itself responsible for closing the source stream. As soon as your program calls Dispose or Close (leaving the using statement scope in your case) then it will dispose the source stream as well. Calling fs.Dispose() in your case. So the file stream is dead after leaving the first using block. It is consistent behavior, all stream classes in .NET that wrap another stream behave this way.
There is one constructor for StreamReader that allows saying that it doesn't own the source stream. It is however not accessible from a .NET program, the constructor is internal.
In this particular case, you'd solve the problem by not using the using-statement for the StreamReader. That's however a fairly hairy implementation detail. There's surely a better solution available to you but the code is too synthetic to propose a real one.
The purpose of Dispose() is to clean up resources when you're finished with the stream. The reason the reader impacts the stream is because the reader is just filtering the stream, and so disposing the reader has no meaning except in the context of it chaining the call to the source stream as well.
To fix your code, just use one reader the entire time:
using (FileStream fs = new FileStream(fileToReadPath, FileMode.Open))
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
fs.Seek(0, SeekOrigin.Begin); // ObjectDisposedException not thrown now
text = reader.ReadToEnd();
Console.WriteLine(text);
}
Edited to address comments below:
In most situations, you do not need to access the underlying stream as you do in your code (fs.Seek). In these cases, the fact that StreamReader chains its call to the underlying stream allows you to economize on the code by not using a usings statement for the stream at all. For example, the code would look like:
using (StreamReader reader = new StreamReader(new FileStream(fileToReadPath, FileMode.Open)))
{
...
}
Using defines a scope, outside of which an object will be disposed, thus the ObjectDisposedException. You can't access the StreamReader's contents outside of this block.
I agree with your question. The biggest issue with this intentional side-effect is when developers don't know about it and are blindly following the "best practice" of surrounding a StreamReader with a using. But it can cause some really hard to track down bugs when it is on a long-lived object's property, the best (worst?) example I've seen is
using (var sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
body = sr.ReadToEnd();
}
The developer had no idea the InputStream is now hosed for any future place that expects it to be there.
Obviously, once you know the internals you know to avoid the using and just read and reset the position. But I thought a core principle of API design was to avoid side effects, especially not destroying data you are acting upon. Nothing inherent about a class that supposedly is a "reader" should clear the data it reads when done "using" it. Disposing of the reader should release any references to the Stream, not clear the stream itself. The only thing I can think is that the choice had to be made since the reader is altering other internal state of the Stream, like the position of the seek pointer, that they assumed if you are wrapping a using around it you are intentionally going to be done with everything. On the other hand, just like in your example, if you are creating a Stream, the stream itself will be in a using, but if you are reading a Stream that was created outside of your immediate method, it is presumptuous of the code to clear the data.
What I do and tell our developers to do on Stream instances that the reading code doesn't explicitly create is...
// save position before reading
long position = theStream.Position;
theStream.Seek(0, SeekOrigin.Begin);
// DO NOT put this StreamReader in a using, StreamReader.Dispose() clears the stream
StreamReader sr = new StreamReader(theStream);
string content = sr.ReadToEnd();
theStream.Seek(position, SeekOrigin.Begin);
(sorry I added this as an answer, wouldn't fit in a comment, I would love more discussion about this design decision of the framework)
Dispose() on parent will Dispose() all owned streams. Unfortunately, streams don't have Detach() method, so you have to create some workaround here.
I don't know why, but you can leave your StreamReader undisposed. That way your underlying stream won't be disposed, even when StreamReader got collected.
How do I read and write on a text file without getting the exception that "File is already in use by another app"??
I tried File.readalltext() and File.Appendalltext() functions..I'm just starting out with filestream.
Which would work out best in my scenario? I would appreciate some code snipplets too ..
Thanks
This is all to do with the lock and sharing semantics that you request when opening the file.
Instead of using the shortcut approach of File.ReadAllText(), try looking into using a System.IO.FileStream and a System.IO.StreamReader / System.IO.StreamWriter.
To open a file:
using (var fileStream = new FileStream(#"c:\myFile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var streamReader = new StreamReader(fileStream))
{
var someText = streamReader.ReadToEnd();
}
Note the FileShare.ReadWrite - this is telling the stream to allow sharing to either other readers or other writers.
For writing try something like
using (var fileStream = new FileStream(#"c:\myFile", FileMode.Create, FileAccess.Write, FileShare.Read))
using (var streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine("some text");
}
Note the FileShare.Read - this is telling the stream to allow sharing to readers only.
Have a read around the System.IO.FileStream and its constructor overloads and you can tailor exactly how it behaves to suit your purpose.
You need to make sure the file is not being used by any other application.
With your own application, you cannot read from a file multiple times without closing the stream between reads.
You need to find out why the file is in use - a tool like FileMon can help finding out.