I'm experimenting with shortening and refining my code as much as possible. One of the ideas I had involves returning a string from a single line of code, employing using to ensure that the accessed file becomes available again when the transaction is complete. My objective is to get as close to a single line of code as possible, however I am having trouble finding a way around the immutability of strings.
The following code is invalid:
string sample()
{
try{ using( string example = (new StreamReader
(new FileStream
("", FileMode.Open, FileAccess.Read),
Encoding.UTF8).ReadToEnd())) }
//I haven't quite worked out returning the value yet, but this is irrelevant here
}
The working code would be as follows:
string sample()
{
FileStream fs = new FileStream("", FileMode.Open, FileAccess.Read);
try{
using(StreamReader rdr = new StreamReader(fs);
return rdr.ReadToEnd();
}
}
I could easily simplify this by doing the following:
string sample()
{
try
{
return (new StreamReader(new FileStream
("", FileMode.Open, FileAccess.Read),
Encoding.UTF8).ReadToEnd());
}
}
However, that may not close the file after the transaction is complete (if that's wrong please let me know). Is there a way to work around the immutability of a string here, or am I looking for the impossible?
It looks like you want a way to create an expression from a using statement. You can create a function:
public static T Use<TRec, T>(TRec resource, Func<TRec, T> f) where TRec : IDisposable
{
using(resource) { return f(resource); }
}
then do
string s = Use(new StreamReader(new FileStream("", FileMode.Open, FileAccess.Read), Encoding.UTF8), sr => sr.ReadToEnd());
Related
The new Visual Studio 2012 is complaining about a common code combination I have always used. I know it seems like overkill but I have done the following in my code 'just to be sure'.
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var sr = new StreamReader(fs))
{
// Code here
}
}
Visual studio is 'warning' me that I am disposing of fs more than once. So my question is this, would the proper way to write this be:
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var sr = new StreamReader(fs);
// do stuff here
}
Or should I do it this way (or some other variant not mentioned).
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var sr = new StreamReader(fs))
{
// Code here
}
I searched several questions in StackOverflow but did not find something that addressed the best practice for this combination directly.
Thank you!
The following is how Microsoft recommends doing it. It is long and bulky, but safe:
FileStream fs = null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (TextReader tr= new StreamReader(fs))
{
fs = null;
// Code here
}
}
finally
{
if (fs != null)
fs.Dispose();
}
This method will always ensure that everything is disposed that should be despite what exceptions may be thrown. For example, if the StreamReader constructor throws an exception, the FileStream would still be properly disposed.
Visual studio is 'warning' me that I am disposing of fs more than once.
You are, but that is fine. The documentation for IDisposable.Dispose reads:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.
Based on that, the warning is bogus, and my choice would be to leave the code as it is, and suppress the warning.
As Dan's answer only appears to work with StreamWriter, I believe this might be the most acceptable answer.
(Dan's answer will still give the disposed twice warning with StreamReader - as Daniel Hilgarth and exacerbatedexpert mentions, StreamReader disposes the filestream)
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
string line;
while ((line = tr.ReadLine()) != null)
{
// Do work here
}
}
This is very similar to Daniel Hilgarth's answer, modified to call dispose via the Using statement on StreamReader as it is now clear StreamReader will call dispose on FileStream (According to all the other posts, documentation referenced)
Update:
I found this post. For what it is worth.
Does disposing streamreader close the stream?
Yes, the correct way would be to use your first alternative:
using (FileStream fs = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
// do stuff here
}
The reason is the following:
Disposing the StreamReader only disposes the FileStream so that's actually the only thing you need to dispose.
Your second option (just the inner "using") is no solution as it would leave the FileStream undisposed if there was an exception inside the constructor of the StreamReader.
It's because the way you used StreamReader disposes the stream when it is disposed. So, if you dispose the stream too, it's being disposed twice. Some consider this a flaw in StreamReader--but it's there none-the-less. In VS 2012 (.NET 4.5) there is an option in StreamReader to not dispose of the stream, with a new constructor: http://msdn.microsoft.com/en-us/library/gg712952
Two solutions:
A) You trust Reflector or Documentation and you know *Reader and *Writer will close the underlying *Stream. But warning: it won't work in case of a thrown Exception. So it is not the recommended way:
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
// Code here
}
B) You ignore the warning as documentation states The object must not throw an exception if its Dispose method is called multiple times. It's the recommended way, as it's both a good practice to always use using, and safe in case of a thrown Exception:
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
[...]
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (TextReader tr = new StreamReader(fs))
{
// Code here
}
}
Given all the nonsense this (perfectly legitimate!) question generated, this would be my preference:
FileStream fs = null;
TextReader tr= null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tr= new StreamReader(fs);
// Code here
}
finally
{
if (tr != null)
tr.Dispose();
if (fs != null)
fs.Dispose();
}
The links below illustrate perfectly legal syntax. IMO, this "using" syntax is far preferable to nested "using". But I admit - it does not solve the original question:
http://blogs.msdn.com/b/ericgu/archive/2004/08/05/209267.aspx
.NET - Replacing nested using statements with single using statement
IMHO...
Which method is more efficient (time, memory, resource-releasing, exception scenario) ?
public static string getFileData(string filePath)
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (StreamReader r = new StreamReader(fs))
{
return r.ReadToEnd();
}
}
}
OR
public static string getFileData(string filePath)
{
return (new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)).ReadToEnd());
}
first without a doubt - you're atleast disposing of the resources you're using. In your second case, maybe if it was being stored into a static variable so only reading once it might be okay, but still not disposing diligently
CLR will generate one code approximately for both code, so two code are same
Here is my code. :
FileStream fileStreamRead = new FileStream(pathAndFileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
FileStream fileStreamWrite = new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
StreamWriter sw = new StreamWriter(fileStreamWrite);
int readIndex = 0;
using (StreamReader sr = new StreamReader(fileStreamRead))
{
while (!sr.EndOfStream) {
Console.WriteLine("eof" + sr.EndOfStream);
readIndex++;
Console.WriteLine(readIndex);
string currentRecord = "";
currentRecord = sr.ReadLine();
if (currentRecord.Trim() != "")
{
Console.WriteLine("Writing " + readIndex);
sw.WriteLine(currentRecord);
}
else {
Console.WriteLine("*******************************************spaces ***********************");
}
}
It is cutting off 2 lines with one test file and half a line, and then 1 line and half a line with the other test file I am running it against.
I am not a streamreader/writer expert you can probably see.
Any ideas or suggestions would be greatly appreciated as this is driving me batty. I am sure it is me using these incorrectly.
You are missing Flush/Close or simply using for your writer.
using(FileStream fileStreamWrite =
new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
{
using(StreamWriter sw = new StreamWriter(fileStreamWrite))
{
// .... write everything here
}
}
Right after the closing brace of the using statement, do this:
sw.Flush();
sw.Close();
There, that should do it.
You need to Flush your StreamWriter. A StreamWriter has a buffer, and it writes to disk only when the buffer is full. By flushing at the end you make sure all the text in the buffer is written to the disk.
In addition to other answers (use using, and/or flush/close), would say that they do not actually respond to the question: "why it may cut several lines."
I have an idea on subject that it is related to a fact that you use StreamReader and call EndOfStream twice: in a while loop header, and another inside it.
The only possible way of understanding if the stream ends is try to read some data from it. So I suspect EnfOfStream does it, and reading it twice, may create a problem in stream processing.
To resolve an issue:
Or use simple TextReader, considering that you are reading text file (seems to me)
Or change your logic to call only once, so no more call to Console.WriteLine("eof" + sr.EndOfStream);
Or change your logic, so do not use EndOFStream at all, but read line by line till the line is null.
You're not using StreamWriter properly. Also, since you're always reading lines, I would use a method that already does all that for you (and manages it properly).
using (var writer = new StreamWriter("path"))
{
foreach(var line in File.ReadLines("path"))
{
if (string.IsNullOrWhiteSpace(line))
{ /**/ }
else
{ /**/ }
}
}
... or ...
/* do not call .ToArray or something that will evaluate this _here_, let WriteAllLines do that */
var lines = File.ReadLines("path")
.Select(line => string.IsNullOrWhiteSpace(line) ? Stars : line);
var encoding = Encoding.ASCII; // whatever is appropriate for you.
File.WriteAllLines("path", lines, encoding);
The new Visual Studio 2012 is complaining about a common code combination I have always used. I know it seems like overkill but I have done the following in my code 'just to be sure'.
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var sr = new StreamReader(fs))
{
// Code here
}
}
Visual studio is 'warning' me that I am disposing of fs more than once. So my question is this, would the proper way to write this be:
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var sr = new StreamReader(fs);
// do stuff here
}
Or should I do it this way (or some other variant not mentioned).
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var sr = new StreamReader(fs))
{
// Code here
}
I searched several questions in StackOverflow but did not find something that addressed the best practice for this combination directly.
Thank you!
The following is how Microsoft recommends doing it. It is long and bulky, but safe:
FileStream fs = null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (TextReader tr= new StreamReader(fs))
{
fs = null;
// Code here
}
}
finally
{
if (fs != null)
fs.Dispose();
}
This method will always ensure that everything is disposed that should be despite what exceptions may be thrown. For example, if the StreamReader constructor throws an exception, the FileStream would still be properly disposed.
Visual studio is 'warning' me that I am disposing of fs more than once.
You are, but that is fine. The documentation for IDisposable.Dispose reads:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.
Based on that, the warning is bogus, and my choice would be to leave the code as it is, and suppress the warning.
As Dan's answer only appears to work with StreamWriter, I believe this might be the most acceptable answer.
(Dan's answer will still give the disposed twice warning with StreamReader - as Daniel Hilgarth and exacerbatedexpert mentions, StreamReader disposes the filestream)
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
string line;
while ((line = tr.ReadLine()) != null)
{
// Do work here
}
}
This is very similar to Daniel Hilgarth's answer, modified to call dispose via the Using statement on StreamReader as it is now clear StreamReader will call dispose on FileStream (According to all the other posts, documentation referenced)
Update:
I found this post. For what it is worth.
Does disposing streamreader close the stream?
Yes, the correct way would be to use your first alternative:
using (FileStream fs = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
// do stuff here
}
The reason is the following:
Disposing the StreamReader only disposes the FileStream so that's actually the only thing you need to dispose.
Your second option (just the inner "using") is no solution as it would leave the FileStream undisposed if there was an exception inside the constructor of the StreamReader.
It's because the way you used StreamReader disposes the stream when it is disposed. So, if you dispose the stream too, it's being disposed twice. Some consider this a flaw in StreamReader--but it's there none-the-less. In VS 2012 (.NET 4.5) there is an option in StreamReader to not dispose of the stream, with a new constructor: http://msdn.microsoft.com/en-us/library/gg712952
Two solutions:
A) You trust Reflector or Documentation and you know *Reader and *Writer will close the underlying *Stream. But warning: it won't work in case of a thrown Exception. So it is not the recommended way:
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
// Code here
}
B) You ignore the warning as documentation states The object must not throw an exception if its Dispose method is called multiple times. It's the recommended way, as it's both a good practice to always use using, and safe in case of a thrown Exception:
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
[...]
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (TextReader tr = new StreamReader(fs))
{
// Code here
}
}
Given all the nonsense this (perfectly legitimate!) question generated, this would be my preference:
FileStream fs = null;
TextReader tr= null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tr= new StreamReader(fs);
// Code here
}
finally
{
if (tr != null)
tr.Dispose();
if (fs != null)
fs.Dispose();
}
The links below illustrate perfectly legal syntax. IMO, this "using" syntax is far preferable to nested "using". But I admit - it does not solve the original question:
http://blogs.msdn.com/b/ericgu/archive/2004/08/05/209267.aspx
.NET - Replacing nested using statements with single using statement
IMHO...
If I have a using block, where I create an object (e.g. a FileStream object), and that object fails to create (returns null, throws an exception, etc.), does the code in the block still execute?
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
// do stuff with fs here
}
// do more stuff after
If the FileStream constructor were to return null (if the FileStream constructor always returns a valid object, let's just say for sake of argument that it is possible to return null), would the code inside execute? Or would it skip over the "do stuff with fs here" code?
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// do stuff with fs here
}
// do more stuff after
is equivalent to:
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
try
{
// do stuff with fs here
}
finally
{
if (fs != null)
{
((IDisposable)fs).Dispose();
}
}
// do more stuff after
So to answer your question:
If the FileStream constructor were to return null (if the FileStream
constructor always returns a valid object, let's just say for sake of
argument that it is possible to return null), would the code inside
execute?
Yes, it will.
Obviously everyone familiar with the C# specification knows that a constructor (no matter for which type) can never return null which kind of makes your question a bit unrealistic.
The exception would get handled as usual i.e. by the enclosing try...catch if you have one or by the system.
If it throws an exception, it's definitely not going to execute. If no exception is thrown, it's going to try and execute the block. Though if it were to return null, my guess is it wouldn't get far before throwing an exception from inside and quitting.
The code will execute regardless of that so you'll need to protect your code against it. Take for example this console application, the WriteLine will execute.
class Program
{
static void Main(string[] args)
{
using (null)
{
Console.WriteLine("Hello.");
}
}
}