c# Writing to a file without using using{} - c#

I'm writing a little application whereby I want to write the results of the operations to a file.
Basically what I want to do is open a stream to a file (I'm thinking FileStream, but am open to suggestions), write data to the file, then close it at a later date.
So I've got a class called ReportFile, with methods:
.Create( string path )
.WriteInfo( string a, string b, string c ) ; //Or something like this...
//Then sometime in the future
.Close()
So the class using the ReportFile class will create an instance, call WriteInfo(..) multiple times until it is finished doing whatever it needs to do, then call Close() at some point in the future.
Now I know I need to implement a Dispose pattern on the ReportFile class to ensure that if anything goes screwey that the handle to the file gets appropriately dealt with.
However I haven't been able to find anything thus far on the interweb showing a good way of keeping the file open and then checking to see if it needs to be closed, most of the examples just open the file do the writing, then close it - all within a using{} construct.
In the ReportFile class I want to be able to check if the FileStream instance is not closed so that I can close it and free up resource.
Anyone know of a good link to reference or any other advice ?
(Ohh I should mention that I don't do C# full time, it's only a hobby thing, so if this is a dumb question, my apologies ;-)

Is there a particular reason that you have to keep the file open?
In this situation I would simply open the file each time using FileMode.Append (or pass append=true to StreamWriter ctor) and then close it again afterwards with a using. eg:
void WriteInfo(string text)
{
// Second parameter to StreamWriter ctor is append = true
using(StreamWriter sw = new StreamWriter(logFilePath, true))
{
sw.WriteLine(text);
}
}
Taking this approach you can don't really need a Create() or Close() method. The append=true will create the file if it does not exist.

The ReportFile would just have a TextWriter instance variable - which you would dispose within your own Dispose() method.
Why do you want to have an explicit Close() method, btw? Your callers should be using a using statement anyway, so why would they want to explicitly call Close as well?

Justa, i think that you're overthinking this feature a bit. The reason that you're seeing examples with the using construct is that using{} with file write is quite fast and safe.
Chances are that you're not opening and closing the file several times a second so there's no need to keep it open all the time and thus risking leaving the app without closing the file (which is a PITA to fix after the fact.) Using the using construct makes certain that the resource, your file in this case, is released and closed properly.
Another piece of advice for programming: don't worry about efficiency at the outset. Get it working first the simplest way you can and improve speed/performance later only if it's necessary.

public void Create(string path) {
mStream = new FileStream(path);
}
public void Dispose() {
if (mStream != null)
mStream.Dispose();
}

I would suggest using the "using" construct and keep the file open only whilst saving.
An idea might be to build the content in memory then save it when you're ready. using a StringBuilder for example.

In the case you simply won't use a using {} construct, you can use the IDisposable interface: http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx

Related

ASP.Net C# Active Directory: Inherited an application with thread.sleep() after each DirectoryEntry.MoveTo() calls

So I'm working on this application that was developed by other people that are not involved with the project anymore. As stated in the title there are a few thread.sleep() calls that have me scratching my head. I have no experience working with AD.
The worst offender is the following one with a 50 second sleep in a class that inherits Principle.
public class Computer:ComputerPrinciple
{
...
public void MoveToOu(string ou)
{
var userObject = (DirectoryEntry)GetUnderlyingObject();
var newParentOu = new DirectoryEntry("LDAP://" + ou);
userObject.MoveTo(newParentOu);
Thread.Sleep(50000);
userObject.Close();
newParentOu.Close();
}
...
}
There is nothing that explains the reason but I suspect it was an issue with the page refreshing before the changes were fully committed (?). One thing I'm pretty sure of is that Thread.Sleep(50000) is not the correct solution to whatever problem they we're having.
I'd like to hear from people who have experience with this if there is indeed some sort of issue that this would "fix" and what would be the incorporate solution.
Also I'm thinking I should use the "using" directive but I'm wondering about disposing the UnderlyingObject or even just closing it because this code is called from something like this where computer is the principle in witch the move code is
computer.UpdateComputerDescription(collection);
computer.UpdateComputerOu(collection); <--- offending MoveToOu method is called in here
computer.UpdateComputerIsActivedProperty(collection);
computer.Save();
Would closing or disposing of the underlyingObject have a side effect on the methods after that call?
Any input would be welcome.
This use of Thread.Sleep is likely a workaround for not calling CommitChanges.
From documentation
If UsePropertyCache is true, call the CommitChanges method on the new object to make the move permanent
It looks like they were waiting for the cache to flush using an empirical delay.
Second, wrapping any IDisposable you create inside MoveToOu in using will not break anything. It is the correct way to go. Objects used, but not created, inside MoveToOu scope should not be disposed here, but rather be left to the container class dispose mechanism.

How can I make a data structure persist after the application is closed?

Ok, so let me take a simple example of what I'm trying to describe. This is probably a very "n00b" question, and yet I've ready plenty of programming books and they never have examples like this.
Let's say I have a program like
public class Program
{
private static List<string> _input = new List<string>();
public static void Main()
{
string line;
while((line = Console.ReadLine()) != null)
{
Program._input.Add(line);
}
return 0;
}
}
except want to modify it so that the next time I launch, the lines I added to input the previous time I ran the program are still there. Is there a way to do this (without writing the list to a text file or something like that)? If so, how?
Once your application is closed, everything stored in variables is lost when your application is destroyed.
The only way to persist data is to store it somewhere outside of your program. The most common are files or databases. In your case, you're just storing lines of text so I'd probably go with a file.
You can easily write to the file when the application is closing and then read from the file when the application starts.
If you want save all value of your class you can use a Serialization
you can have some example here : Examples of XML Serialization
But in all case you need to write in a file you can keep it in RAM.
Whenever you close your program, Windows frees memory. Only files are preserved.
Writing file is not evil but just one simple statement.
File.WriteAllLines("lines.txt", _input);
Reading file is also easy.
_input.AddRange(File.ReadAllLines("lines.txt"));
When application is closed on operating system, it is taken out from the computer memory...so you have to save its state to some kind of file or storage devices... as far as I concern that is the only way

Do I need to explicitly close the StreamReader in C# when using it with string variable?

This is my code:
string data = "...";
var stream = new StreamReader(data);
Is that okay not call the Close() method?
Yes, otherwise you will have a memory leak. Wrap your StreamReader in a using statement so you don't have to worry about cleaning it up e.g.
using (var reader = StreamReader(data))
{
...
}
Have you actually compiled and run your code?
The StreamReader(string) constructor treats the input as a file name!
Unless this isn't really your code and you meant StringReader, your code is trying to stream the contents of the file name specified in data, which is likely to throw a FileNotFoundException because the file probably doesn't exist. And if it did, you would certainly need to call Close or integrate your code into a using statement to release the file handle.
You might also want to take a look at this tutorial on msdn:
http://msdn.microsoft.com/en-us/library/aa355056.aspx
which tells you about things you need to be careful with the using statement. Other than that, using is the way to go.
Another pretty good article on codeProject. Worth reading.
The resource will not be accessable to other processes until your process stops using it so you should close it if you don't need it

Creating an empty file in C#

What's the simplest/canonical way to create an empty file in C#/.NET?
The simplest way I could find so far is:
System.IO.File.WriteAllLines(filename, new string[0]);
Using just File.Create will leave the file open, which probably isn't what you want.
You could use:
using (File.Create(filename)) ;
That looks slightly odd, mind you. You could use braces instead:
using (File.Create(filename)) {}
Or just call Dispose directly:
File.Create(filename).Dispose();
Either way, if you're going to use this in more than one place you should probably consider wrapping it in a helper method, e.g.
public static void CreateEmptyFile(string filename)
{
File.Create(filename).Dispose();
}
Note that calling Dispose directly instead of using a using statement doesn't really make much difference here as far as I can tell - the only way it could make a difference is if the thread were aborted between the call to File.Create and the call to Dispose. If that race condition exists, I suspect it would also exist in the using version, if the thread were aborted at the very end of the File.Create method, just before the value was returned...
File.WriteAllText("path", String.Empty);
or
File.CreateText("path").Close();
System.IO.File.Create(#"C:\Temp.txt");
As others have pointed out, you should dispose of this object or wrap it in an empty using statement.
using (System.IO.File.Create(#"C:\Temp.txt"));
To avoid accidentally overwriting an existing file use:
using (new FileStream(filename, FileMode.CreateNew)) {}
...and handle the IOException which will occur if the file already exists.
File.Create, which is suggested in other answers, will overwrite the contents of the file if it already exists. In simple cases you could mitigate this using File.Exists(). However something more robust is necessary in scenarios where multiple threads and/or processes are attempting to create files in the same folder simultaneously.
You can chain methods off the returned object, so you can immediately close the file you just opened in a single statement.
File.Open("filename", FileMode.Create).Close();
A somewhat common use case for creating an empty file is to trigger something else happening in a different process in the absence of more sophisticated in process communication. In this case, it can help to have the file creation be atomic from the outside world's point of view (particularly if the thing being triggered is going to delete the file to "consume" the trigger).
So it can help to create a junk name (Guid.NewGuid.ToString()) in the same directory as the file you want to create, and then do a File.Move from the temporary name to your desired name. Otherwise triggered code which checks for file existence and then deletes the trigger may run into race conditions where the file is deleted before it is fully closed out.
Having the temp file in the same directory (and file system) gives you the atomicity you may want. This gives something like.
public void CreateEmptyFile(string path)
{
string tempFilePath = Path.Combine(Path.GetDirectoryName(path),
Guid.NewGuid.ToString());
using (File.Create(tempFilePath)) {}
File.Move(tempFilePath, path);
}
Path.GetTempFileName() will create a uniquly named empty file and return the path to it.
If you want to control the path but get a random file name you can use GetRandomFileName to just return a file name string and use it with Create
For example:
string fileName=Path.GetRandomFileName();
File.Create("custom\\path\\" + fileName);

How to save the output of a console application

I need advice on how to have my C# console application display text to the user through the standard output while still being able access it later on. The actual feature I would like to implement is to dump the entire output buffer to a text file at the end of program execution.
The workaround I use while I don't find a cleaner approach is to subclass TextWriter overriding the writing methods so they would both write to a file and call the original stdout writer. Something like this:
public class DirtyWorkaround {
private class DirtyWriter : TextWriter {
private TextWriter stdoutWriter;
private StreamWriter fileWriter;
public DirtyWriter(string path, TextWriter stdoutWriter) {
this.stdoutWriter = stdoutWriter;
this.fileWriter = new StreamWriter(path);
}
override public void Write(string s) {
stdoutWriter.Write(s);
fileWriter.Write(s);
fileWriter.Flush();
}
// Same as above for WriteLine() and WriteLine(string),
// plus whatever methods I need to override to inherit
// from TextWriter (Encoding.Get I guess).
}
public static void Main(string[] args) {
using (DirtyWriter dw = new DirtyWriter("path", Console.Out)) {
Console.SetOut(dw);
// Teh codez
}
}
}
See that it writes to and flushes the file all the time. I'd love to do it only at the end of the execution, but I couldn't find any way to access to the output buffer.
Also, excuse inaccuracies with the above code (had to write it ad hoc, sorry ;).
The perfect solution for this is to use log4net with a console appender and a file appender. There are many other appenders available as well. It also allows you to turn the different appenders off and on at runtime.
I don't think there's anything wrong with your approach.
If you wanted reusable code, consider implementing a class called MultiWriter or somesuch that takes as input two (or N?) TextWriter streams and distributes all writs, flushes, etc. to those streams. Then you can do this file/console thing, but just as easily you can split any output stream. Useful!
Probably not what you want, but just in case... Apparently, PowerShell implements a version of the venerable tee command. Which is pretty much intended for exactly this purpose. So... smoke 'em if you got 'em.
I would say mimic the diagnostics that .NET itself uses (Trace and Debug).
Create a "output" class that can have different classes that adhere to a text output interface. You report to the output class, it automatically sends the output given to the classes you have added (ConsoleOutput, TextFileOutput, WhateverOutput).. And so on.. This also leaves you open to add other "output" types (such as xml/xslt to get a nicely formatted report?).
Check out the Trace Listeners Collection to see what I mean.
Consider refactoring your application to separate the user-interaction portions from the business logic. In my experience, such a separation is quite beneficial to the structure of your program.
For the particular problem you're trying to solve here, it becomes straightforward for the user-interaction part to change its behavior from Console.WriteLine to file I/O.
I'm working on implementing a similar feature to capture output sent to the Console and save it to a log while still passing the output in real time to the normal Console so it doesn't break the application (eg. if it's a console application!).
If you're still trying to do this in your own code by saving the console output (as opposed to using a logging system to save just the information you really care about), I think you can avoid the flush after each write, as long as you also override Flush() and make sure it flushes the original stdoutWriter you saved as well as your fileWriter. You want to do this in case the application is trying to flush a partial line to the console for immediate display (such as an input prompt, a progress indicator, etc), to override the normal line-buffering.
If that approach has problems with your console output being buffered too long, you might need to make sure that WriteLine() flushes stdoutWriter (but probably doesn't need to flush fileWriter except when your Flush() override is called). But I would think that the original Console.Out (actually going to the console) would automatically flush its buffer upon a newline, so you shouldn't have to force it.
You might also want to override Close() to (flush and) close your fileWriter (and probably stdoutWriter as well), but I'm not sure if that's really needed or if a Close() in the base TextWriter would issue a Flush() (which you would already override) and you might rely on application exit to close your file. You should probably test that it gets flushed on exit, to be sure. And be aware that an abnormal exit (crash) likely won't flush buffered output. If that's an issue, flushing fileWriter on newline may be desirable, but that's another tricky can of worms to work out.

Categories

Resources