I've written the following code:
public static class PLog
{
private static FileStream logFileStream;
private static string logFilePath;
public static void Initialize()
{
logFilePath = PSettings.IO.dirLogs + "log_" + DateTime.Now.ToString("ddMMyy_HHmmss") + ".txt";
if (!Directory.Exists(PSettings.IO.dirLogs)) Directory.CreateDirectory(PSettings.IO.dirLogs);
logFileStream = new FileStream(logFilePath, FileMode.Create);
}
public static void WriteLine(string text)
{
byte[] textArray = Encoding.ASCII.GetBytes("[" + DateTime.Now.ToString("dd.MM.yyyy - HH:mm:ss") + "] " + text + "\n");
logFileStream.Write(textArray, 0, textArray.Length);
}
public static void Close()
{
logFileStream.Close();
}
}
But when I call it like this, it doesn't write anything to the file:
PLog.Initialize();
PLog.WriteLine("test");
PLog.Close();
The file was created but it had the size of 0 bytes.
FileStream implements IDisposable.
It is rarely a good idea to use it in a static context like you show in your code because it is hard to really ensure that IDisposable.Dispose() gets called to properly clean up the stream.
If you can, use FileStream with the using keyword to ensure that Dispose() is called
using (FileStream fs = new FileStream(logFilePath, FileMode.Create))
{
// Do stuff with fs
}
If you must keep your current structure, check that Close() really is called (and you're not e.g. getting an Exception that prevents it from being called).
UPDATE
Regarding your comment to the other answer:
Append Environment.Newline to the end of your string before you write it out.
Alternatively, you can use a StreamWriter, which exposes a WriteLine() method.
You need to use flush to save
logFileStream.Flush();
EDIT:
Close should also flush, but if it happens later it is possible that the buffer gets garbage collected
Related
I'm VERY new to C# so please allow me some ignorance :)
(I've tried searching around to understand the reason for the difference in performance I'm seeing but as of yet don't have a definitive answer so I thought I'd ask the knowledgable audience on here...)
Basically... if I use streamwriter something like:
public static class Logging
{
readonly static object DebugWriter = new object();
public static void Log(string msg)
{
lock (DebugWriter)
{
using (StreamWriter writer = new StreamWriter("Debug.txt", true))
{
writer.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.ffff") + " " + msg);
}
}
}
}
then assuming I send a large amount of text out via this class I see a noticeable hit on CPU.
However if I instead write it something along the lines of:
public static class Logging
{
readonly static object DebugWriter = new object();
static StreamWriter lwriter = new StreamWriter("LocalDrivenDebug.txt", true) { AutoFlush = true };
public static void Log(string msg)
{
lock (DebugWriter)
{
lwriter.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.ffff") + " " + msg);
}
}
}
Then I see pretty much no hit on the CPU at all.
Is the above caning the CPU purely through inialisation and disposal caused by the using statement? (If so what the hell is C# doing to eat so much CPU???) - Given it's a static class and I've forced autoflush, surely the same applies to the second version or does its disposal get acted on differently and hence chew up less CPU time?
I can only assume I'm missing something obvious. So hopefully someone out there can enlighten me as I 'thought' you were supposed to use the using statement as a safer/more convenient way of doing the disposal?
The second snippet has two properties :
- It doesn't recreate the writer, which can help if you call log many times.
- It doesn't dispose the writer, which means the text you are writing is not flushed to disk yet, but rather kept in memory for later flushing ! On the other end, you write on disk every call to log with the first snippet.
All in all, these two effects should explain the noticeable difference you see :)
Where to dispose StreamWriter if I need it during entire application lifetime? I'm going to dispose it in destructor, will that work? I have to dispose to flush data, and I don't want to use AutoFlush feature because from msdn: "You can get better performance by setting AutoFlush to false, assuming that you always call Close (or at least Flush) when you're done writing with a StreamWriter."
So should i Dispose in destructor like in the code below?
class Log
{
private static StreamWriter swLog = new StreamWriter("logMAIN.txt");
static ~Log()
{
swLog.Dispose();
}
public static void Push(LogItemType type, string message)
{
swLog.WriteLine(type + " " + DateTime.Now.TimeOfDay + " " + message);
}
}
upd instead of Dispose i meant to call Close but it is not improtant in this case because they seems doing exactly the same.
You seem to be basing your decision not to flush on some performance information from MSDN. That's not where I'd start.
Do you have evidence that using AutoFlush causes you significant performance problems?
Have you considered alleviating these performance problems in a different way, e.g. having a single thread writing to the StreamWriter, either auto-flushing or periodically flushing every 20 seconds or whatever?
You haven't told us what kind of application you're writing, mind you - that can make a significant difference in terms of how much you know about shutdown.
Also note that the code you've given isn't thread-safe to start with. You could end up using the StreamWriter from multiple threads concurrently; I doubt that StreamWriter is particularly designed for that scenario.
The problem really is the way the StreamWriter is initialized. Using a regular object like this
using (var logger = new Log())
{
app.Run();
}
The StreamWriter can still be a static field in the Log class, but is initialized and disposed at known points in time rather than using a static initializer.
For this to work you will need to let you log class implement the IDisposable interface and dispose the StreamWriter in the Dispose method like this:
class Log: IDisposable
{
private static StreamWriter swLog;
public Log()
{
swLog = new StreamWriter("logMAIN.txt");
}
public void Dispose()
{
swLog.Dispose();
}
public static void Push(LogItemType type, string message)
{
swLog.WriteLine(type + " " + DateTime.Now.TimeOfDay + " " + message);
}
}
Also note how the Log will be disposed even if an exception is thrown.
I know the answer must be out there somewhere, I applied suggestions both from many other questions and from MSDN itself but I'm probably overlooking something here.
This is my method, I use it to dump output to file. lock object declaration attached for clarity.
private static Object fileLock = new Object();
private static void WriteToFile(string msg, bool WriteLine)
{
lock (fileLock)
{
msg = DateTime.Now.ToShortTimeString() + " - " + msg;
FileInfo F = new FileInfo("dump.txt");
using (StreamWriter writer = F.Exists ? F.AppendText() : F.CreateText()) //<--THIS LINE THROWS
{
if (WriteLine)
writer.WriteLine(msg);
else
writer.Write(msg);
}
}
}
Question is: Why does the using line above throws an IOException complaining another process is using the file the 2nd time I call the method ?
I'm calling it like this around my code:
Console.WriteLine(something)
#if(DEBUG)
Extensions.WriteToFile(something,true);
#endif
Again, I'm sure this is a trivial issue and someone else asked something like this getting the right answer, but I'm unable to dig it up.
UPDATE
Refactoring out the FileInfo object and switching to File.XXX methods made the code work fine. I still wonder what the issue was, anyway the issue looks like solved.
#Guffa: declaration has to be private static object fileLock = new object();
#alex: Your code works just fine on my machine although it's a bit too complicated for the task imo.
static void Write(string text, string file)
{
using (StreamWriter sw = File.AppendText(file))// Creates or opens and appends
{
sw.WriteLine(text);
}
}
Maybe some antivirus or indexer locks your dump file.
I have a class which reads data from one file stream and writes to another. I am concerned about closing the streams after the processing has finished in closeFiles().
How would you handle the possibility that the dispose of one stream may throw an exception stopping the dispose of the other stream from being called.?
Should I be calling close and dispose on the streams or just one?
What happens if I catch any errors from the stream disposes and then continue with moving and deleting of the files as shown in lastOperation()?
In a perfect world I'd like to use a using statement in a c++ style initialisation list but I'm pretty sure that's not possible in c#.
EDIT : thanks for the quick responses guys. So what I should be doing is deriving from IDisposable and then change the constructor and add the two disposing methods like this?:
~FileProcessor()
{
Dispose(true);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
sw.Flush();
}
closeFiles();
disposed = true;
}
}
This is basically what I'm doing:
class FileProcessor
{
private string in_filename;
private string out_filename;
private StreamReader sr;
private StreamWriter sw;
bool filesOpen = false;
public FileProcessor(string filename)
{
in_filename = filename;
out_filename = filename + ".out";
openFiles();
}
~FileProcessor()
{
closeFiles();
}
private void openFiles()
{
sr = new StreamReader(in_filename);
sw = new StreamWriter(out_filename);
filesOpen = true;
}
private void closeFiles()
{
if (filesOpen)
{
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
filesOpen = false;
}
}
/* various functions to read, process and write to the files */
public void lastOperation()
{
closeFiles();
File.Delete( in_filename );
Directory.Move(out_filename, outdir + out_filename);
}
}
Your FileProcessor class should not have a destructor. It is of no use but it is expensive.
It should have a Dispose() (and implement the IDisposable interface) to call closeFiles().
And like #marcelo answered, Stream.Dispose() should not throw. You can rely on this for BCL classes.
But you should check each Reader/Writer for null, in case the first one opened but the second one failed:
if (sr != null) sr.Dispose();
if (sw != null) sw.Dispose();
Your filesOpen can't cover both.
I think it is a good practise to have your class implements IDisposable interface if you are using IDisposable object inside it.
Then, you should make sure that, in your Dispose() implementation, don't throw exceptions. If every object you dispose makes this guarantee, your client will be safe.
Dispose methods should never throw exceptions. There's even a code analysis tool warning for this.
In C#, using does exist. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object's resources.
If your StreamReader and StreamWriter implement IDisposable, you can put them in a using block, and they will be disposed of cleanly when you have finished with them.
using(var sr = new StreamReader(in_filename)) {
// Perform reader actions
}
// Reader will now be disposed.
I have a class DocumentGenerator which wraps a MemoryStream. So I have implemented IDisposable on the class.
I can't see how/where I can possibly dispose it though.
This is my current code, which performs a file download in MVC:
using (DocumentGenerator dg = DocumentGenerator.OpenTemplate(path))
{
/* some document manipulation with the
DocumentGenerator goes here ...*/
return File(dg.GetDocumentStream(), "text/plain", filename);
}
This errors as the stream is closed/disposed before the controller has finished with it. How can I make sure my resources are properly disposed in this situation?
EDIT: My implementation of IDisposable at the moment just disposes the MemoryStream. I know it's not a proper implementation, I just used it as a test. Is there something different I could do here to make it work?
public void Dispose()
{
_ms.Dispose();
_ms = null;
}
You don't need to dispose the stream. It will be disposed by the FileStreamResult.WriteFile method. Code excerpt from this class:
public FileStreamResult(Stream fileStream, string contentType) : base(contentType)
{
if (fileStream == null)
{
throw new ArgumentNullException("fileStream");
}
this.FileStream = fileStream;
}
protected override void WriteFile(HttpResponseBase response)
{
Stream outputStream = response.OutputStream;
using (this.FileStream)
{
byte[] buffer = new byte[0x1000];
while (true)
{
int count = this.FileStream.Read(buffer, 0, 0x1000);
if (count == 0)
{
return;
}
outputStream.Write(buffer, 0, count);
}
}
}
Notice the using. When you call File(dg.GetDocumentStream(), "text/plain", filename) from your controller this invokes the constructor which stores the stream into a public property which is disposed during the rendering.
Conclusion: you don't need to worry about disposing the stream obtain with dg.GetDocumentStream().
Just to add to what Darin has said, it's important to note this concept:
public Stream GetDownloadFile(...)
{
using (var stream = new MemoryStream()) {
return stream;
}
}
public Stream GetDownloadFile(...)
{
using (var generator = DocumentGenerator.OpenTemplate(path))
{
// Document manipulation.
return File(generator.GetDocumentStream(), "text/plain", filename);
}
}
Regardless of how you are using it in your method, the using block ensures that Dispose is always called, this is important when you consider to use the result of the using block as a return statement, it won't stop it from being disposed....