代码之家  ›  专栏  ›  技术社区  ›  senschen

为什么StreamWriter不写入文件?

  •  1
  • senschen  · 技术社区  · 10 年前

    我正在使用StreamWriter为我的程序制作日志以写入文件。我有一些代码看起来很有用,但它只做了它应该做的一部分。

    我制作了一个名为Log的简单类(代码如下)。

    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();
    
    }
    }
    

    我做了一个简单的测试程序,效果很好。它执行以下三行:

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

    但在我更大的程序中,我实际上想使用Log类,我得到的只是一个空文件——里面没有文本。其代码如下:

    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);
    

    有人能告诉我为什么这个代码的程序版本不起作用吗?

    2 回复  |  直到 10 年前
        1
  •  3
  •   Steve    10 年前

    我会重写你的Log类以避免结束部分。
    完成写入部分后,只需打开、写入和关闭

    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);
            }
        }
    }
    

    这样,using语句将关闭流,您不必担心关闭它。如果代码中发生意外情况,关闭流可能会非常麻烦。(就像改变代码流的异常)。

    这只是测试和验证代码的一个起点,但您可以按照给定的模式添加一些更复杂的逻辑。例如,您可以添加一个构造函数,该构造函数带有一个标志,用于为每一行添加时间戳(或添加分隔符行的标志,或重新创建文件(如果存在)的标志…)

    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);
            }
        }
    }
    

    最后:请记住,专门的日志库已经过良好测试,可以免费使用。也许你可以花一些时间学习它们

    Log4Net
    NLog

        2
  •  1
  •   Eugene Podskal    10 年前

    1. 在第二个示例中,您没有关闭流,我不确定垃圾收集会发生什么。致电 l.closeLog(); 最后至少能得到一些输出。但这不是一个好主意。如果某个方法在 l.write(); l.closeLog; 。有些不好的文件将被打开,直到GC处理它。

    2. 每次调用都会覆盖文件。可能您需要的是附加数据- http://msdn.microsoft.com/en-us/library/3zc0w663(v=vs.110).aspx 或者更好地更改代码以使用 File.AppendText 方法:

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

    并删除 closeLog 方法,因为这是不必要的。

    编辑:

    最好的方法是只使用无状态的标准方法(正如@leppie所指出的),这样不会泄漏任何资源:

    它是 File.WriteAllText 如果为每个日志实例创建一个日志文件:

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

    File.AppendAllText 如果需要继续现有日志:

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