FileSystemWatcher - 如何将输出管道传输到文本文件?

时间:2011-05-20 18:05:34

标签: c# .net windows

我正在使用FileSystemWatcher类。我试图将输出管道传输到文本文件。我添加了StreamWriter fileWriter = new StreamWriter("test.txt");但没有输出到文件!我哪里错了?

class Program
{
    static void Main(string[] args)
    {
        string dirPath = "C:\\";

        FileSystemWatcher fileWatcher = new FileSystemWatcher(dirPath);
        fileWatcher.IncludeSubdirectories = true;
        fileWatcher.Filter = "*.exe";
        // fileWatcher.Filter = "C:\\$Recycle.Bin";
        //  fileWatcher.Changed += new FileSystemEventHandler(FileWatcher_Changed);
        fileWatcher.Created += new FileSystemEventHandler(FileWatcher_Created);
        //  fileWatcher.Deleted += new FileSystemEventHandler(FileWatcher_Deleted);
        //  fileWatcher.Renamed += new RenamedEventHandler(FileWatcher_Renamed);
        fileWatcher.EnableRaisingEvents = true;
        StreamWriter fileWriter = new StreamWriter("test.txt");
        Console.ReadKey();
    }
}

3 个答案:

答案 0 :(得分:3)

实际写入输出流的代码需要位于FileWatcher_Created事件处理程序中。您只能写出在创建文件时运行的代码中创建的文件。

这意味着事件处理程序需要访问您创建的StreamWriter,否则它需要打开输出文件本身,写一个值,然后每次事件触发时关闭它。

由于您无法将StreamWriter作为参数传递给事件处理程序,因此赋予事件处理程序访问权限的唯一方法是使其成为类级变量,这是您无法做到的来自静态Main方法。您可能必须创建一个类来同时保存FileSystemWatcherStreamWriter,并且只需从Main方法实例化该类。

但等等,还有更多!

如果您正在写入StreamWriter,并且在该时刻创建了另一个文件,该怎么办?你不能让两个线程同时写入一个StreamWriter,或者Bad Things是不可避免的。因此,您需要使用某种锁定来保护对StreamWriter的访问。

答案 1 :(得分:2)

您需要致电

fileWriter.Write(data);

另外,你应该像这样把它包起来:

using(StreamWriter fileWriter = new StreamWriter("test.txt"))
{
    fileWriter.Write(data);
    fileWriter.Flush(); // maybe not necessary
}

这会将数据写入文件系统,它应该触发你的FileSystemWatcher对象。

编辑 - 现场示例

class Program
{    
    static void Main(string[] args)
    {
        string dirPath = "C:\\";
        FileSystemWatcher fileWatcher = new FileSystemWatcher(dirPath); 
        fileWatcher.IncludeSubdirectories = true;  
        fileWatcher.Filter = "*.exe";    
        // fileWatcher.Filter = "C:\\$Recycle.Bin";   
        //  fileWatcher.Changed += new FileSystemEventHandler(FileWatcher_Changed);   
        fileWatcher.Created += new FileSystemEventHandler(FileWatcher_Created);    
        //  fileWatcher.Deleted += new FileSystemEventHandler(FileWatcher_Deleted);  
        //  fileWatcher.Renamed += new RenamedEventHandler(FileWatcher_Renamed);    
        fileWatcher.EnableRaisingEvents = true;      

        // updated code
        using(StreamWriter fileWriter = new StreamWriter("test.txt"))
        {
            var data = true;
            fileWriter.Write(data);
        }

        Console.ReadKey(); 
    }
}

答案 2 :(得分:1)

我只使用Log4Net而不用担心线程安全或任何其他血腥细节。

将它放在AssemblyInfo.cs中:

[assembly: log4net.Config.XmlConfigurator(ConfigFile="Log4Net.config",Watch=true)]

每个要记录某事的类都需要一个记录器。把它放在每个这样的类定义中:

private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ) ;

上述原因是它通过其包含类型识别每个记录器。您的log4net.config可以通过logger过滤/路由/配置日志记录,因此通过这种方式,您可以对日志记录进行大量控制。比方说,你可以在一个看似行为不端的特定类上拨打日志记录详细程度,同时让应用程序的其余部分仅记录错误,例如ERROR和FATAL级别。

您可以通过其中一种ILog方法记录消息(就像Console.WriteLine()string.Format()

Log.InfoFormat( "some-format-string" , ... ) ;

设置log4net.config文件,使其如下所示:

<log4net>

  <appender name="Console" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
      <!-- Pattern to output the caller's file name and line number -->
      <conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
    </layout>
  </appender>

  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <file               value="example.log" />
    <appendToFile       value="true"        />
    <maximumFileSize    value="100KB"       />
    <maxSizeRollBackups value="2"           />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level %thread %logger - %message%newline" />
    </layout>
  </appender>

  <root>
    <level value="DEBUG" />
    <appender-ref ref="Console" />
    <appender-ref ref="RollingFile" />
  </root>

</log4net>

您将登录到控制台和文件。 Log4Net将处理日志文件翻转和所有icky比特。