【问题标题】:Writing to log file: using (... new StreamReader) every time I write a line?写入日志文件:每次我写一行时都使用(... new StreamReader)?
【发布时间】:2014-10-15 03:19:54
【问题描述】:

我编写了一个带有开始和停止按钮的自动化程序,它反复执行各种任务,直到用户单击停止。在程序中,我有几个 Console.WriteLines 显示每个小子任务的结果。我决定将这些转换为 .txt 日志,这样我可以在关闭程序后查看,或者以防它崩溃。

我做了以下 Logger 类:

class Logger
{
    private string _logName;

    public Logger(string logName)
    {
        _logName = logName;

        using (StreamWriter w = File.AppendText(_logName + ".txt"))
        {
            w.WriteLine("-------------------------------");
        }
    }

    public void Log(string logMessage)
    {
        using (StreamWriter w = File.AppendText(_logName + ".txt"))
        {
            w.WriteLine(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " " + logMessage);
        }
        Console.WriteLine(logMessage);
    }
}

问题:在另一个类中,我有一个名为 _logger 的 Logger 实例。每次我想在日志中写一行时,我都会一遍又一遍地调用 _logger.Log。有时,这种情况会很快发生。每次在日志中写一行(在 using 语句中)都创建一个 StreamWriter 的新实例感觉不对。因此,我想到了将 StreamWriter 的实例化放在构造函数中,但这破坏了 using 语句的清理功能,不是吗?

知道如何最好地做到这一点吗?

提前致谢。

【问题讨论】:

标签: c# logging file-io streamwriter textwriter


【解决方案1】:

您可以确保自己在完成时释放/关闭流(因此当此类的实例被释放时):

public sealed class Logger : IDisposable
{
    private string _logName;
    private StreamWriter _stream;

    public Logger(string logName)
    {
        _logName = logName;
        _stream = File.AppendText(_logName + ".txt");
    }

    public void Log(string logMessage)
    {
        _stream.WriteLine(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " " + logMessage);
    }

    public void Dispose()
    {
        _stream.Dispose();
    }
}

现在您还可以将您的记录器与using-statement 一起使用:

using (Logger log = new Logger("Path"))
{
    log.Log("Something");
    // do something else...
    log.Log("Something else");
}

或者您可以使用可用的日志库:.NET logging framework

【讨论】:

  • 就像“最佳实践”一样,如果你不打算遵循protected virtual void Dispose(bool Disposing) 模式(这样做并没有错),你真的应该标记类sealed
  • 蒂姆,不幸的是,这仍然给我留下了与以前相同的问题(刚刚转移到调用类)。在那个类(将文本发送到记录器的那个)中,我只想创建一个 Logger 实例。我不想每次在日志文件中写入一个简单的行时都创建一个 Logger 实例(这种情况非常频繁地连续发生)。
  • @Magnus:不清楚为什么你不能控制只使用Logger 的一个实例。
  • @TimSchmelter Post 说 using(Logger log = new Logger("Path")) { send_string_line_to_be_logged }。所以每次我发送一行,都会创建一个新的 Logger 实例(日志),对吧?
  • @Magnus:是的,但是在您的帖子中,您无法确保流被关闭,这就是为什么您总是在类本身中使用using-statement 的原因。现在您可以在外部使用using(或try-finally),它使您能够将程序的相关部分包装到using 中。如果您有另一个主类来控制您可以在其中保存单个实例的所有内容,可以作为您在自己的Dispose 中处理的字段,或者作为主代码周围的using
【解决方案2】:

您可以使您的记录器类可处置,现在由调用者负责触发清理。

class Logger : IDisposeable
{
    private string _logName;
    private StreamWriter _w;

    public Logger(string logName)
    {
        _logName = logName;

        _w = File.AppendText(_logName + ".txt"))
        _w.WriteLine("-------------------------------");

    }

    public void Log(string logMessage)
    {
        _w.WriteLine(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " " + logMessage);
        Console.WriteLine(logMessage);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if(disposing)
            _w.Dispose();
    }
}

但是,有更强大的预制日志框架,我建议您使用其中之一,而不是自己编写。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多