简体   繁体   中英

Why does my StreamWriter not write to file?

I'm making a log for my program using a StreamWriter to write to a file. I have some code that looks like it works, but its only doing part of what it should.

I made a simple class called Log (code below).

public class Log
{
string path;
StreamWriter fs;
public Log(string fullPathToLogFile)
{
    path = fullPathToLogFile;
    fs = new StreamWriter(path);
    writeLog("Starting log");
}
public void writeLog(string s)
{
    fs.WriteLine(DateTime.Now.ToString("dd-MM-yyyy  H:mm:ss         ") + s);
}
public void closeLog()
{
    writeLog("Closing log");
    fs.WriteLine(); //add a blank line at the end
    fs.Close();

}
}

I made a simple test program that works perfectly. It executes these three lines:

Log l = new Log(@"C:\Users\SADunkerton\Desktop\l.txt");
l.writeLog("testing log");
l.closeLog();

But in my much larger program, where I actually want to use the Log class, all I get is an empty file --no text inside. Its code looks like this:

Log log = new Log(folderPDFs + @"\Log.txt"); //folderPDFs is a parameter of this method--it is a string that is a complete path to a destination folder.
log.writeLog("Beginning conversions");
//do some stuff, including write to the log
log.writeLog("Finished converting.  Success = " + success);

Can anyone tell me why the program version of this code isn't working?

I would rewrite your Log class to avoid the close part.
Just open, write and close after finishing the write part

class MySimpleLog
{
    private string _filename;
    public MySimpleLog(string filename)
    {
        _filename = filename;
    }

    public void AppendText(string msg)
    {
        // Create an instance of StreamWriter to write text to a file.
        // The using statement also closes the StreamWriter.
        using (StreamWriter sw = new StreamWriter(_filename, true))
        {
            // Add some text to the file.
            sw.WriteLine(msg);
        }
    }
}

In this way the using statement will close the stream and you don't have to worry about closing it. Indeed closing the stream could be very troublesome if something unexpected happens in your code. (Like an exception that change your code flow).

This is just a starting point to have the code tested and verified, but you could add some more complex logic following the pattern given. For example you could add a constructor with a flag to add a timestamp for everyline (or a flag to add a separator line, or a flag to recreate the file if exists...)

class MySimpleLog
{
    private string _filename;
    private bool _addtime;
    public MySimpleLog(string filename)
    {
        _filename = filename;
    }
    public MySimpleLog(string filename, bool addtime)
    {
        _filename = filename;
        _addtime = addtime;
    }

    public void AppendText(string msg)
    {
        // Create an instance of StreamWriter to write text to a file.
        // The using statement also closes the StreamWriter.
        using (StreamWriter sw = new StreamWriter(_filename, true))
        {
            // Add some text to the file.
            msg = (_addtime ? DateTime.Now.ToString() + ": " + msg : msg);
            sw.WriteLine(msg);
        }
    }
}

FINALLY: Keep in mind that specialized log libraries exists well tested and free to use. Perhaps you could invest some of your time in learning them

Log4Net
NLog

1. You do not close the stream in the second example - and what will happen on garbage collection I am not sure. Call the l.closeLog(); in the end to at least get some output. But it is not a good idea. What will happen if some method throws between l.write(); and l.closeLog; . Something not good - file will left opened till GC deals with it.

2. You overwrite the file with each call. Probably what you need is to append the data - http://msdn.microsoft.com/en-us/library/3zc0w663(v=vs.110).aspx or even better change your code to use File.AppendText method:

 public void writeLog(string s)
 {
    using (StreamWriter sw = File.AppendText(path)) 
    {
        sw.WriteLine(DateTime.Now.ToString("dd-MM-yyyy  H:mm:ss         ") + s);
    }   
}

And remove the closeLog method, because it is unnecessary.

EDIT:

The best idea is to just use stateless standard methods(as pointed by @leppie), that won't leak any resources:

It is File.WriteAllText if you create one logfile for each log instance:

 public void writeLog(string s)
 {
     File.WriteAllText(path,
         DateTime.Now.ToString("dd-MM-yyyy  H:mm:ss         ") + s);        
 }

or File.AppendAllText if you need to continue already existing logs:

 public void writeLog(string s)
 {
     File.AppendAllText(path,
         DateTime.Now.ToString("dd-MM-yyyy  H:mm:ss         ") + s);        
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM