简体   繁体   English

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

[英]FileSystemWatcher - How to pipe output to text file?

I am using the FileSystemWatcher Class. 我正在使用FileSystemWatcher类。 I am trying to pipe the output to a text file. 我正在尝试将输出传递到文本文件。 I have added the StreamWriter fileWriter = new StreamWriter("test.txt"); 我添加了StreamWriter fileWriter = new StreamWriter("test.txt"); but nothing is output to the file! 但没有任何输出到文件! Where am I going wrong? 我要去哪里错了?

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

The code that actually writes to the output stream needs to be inside the FileWatcher_Created event handler. 实际写入输出流的代码必须位于FileWatcher_Created事件处理程序内。 You can only write out that a file was created in the code that runs when a file is created. 您只能在创建文件时运行的代码中写出该文件已创建。

That means that the event handler needs access to the StreamWriter you've created, or else it needs to open the output file itself, write a value, and then close it every time the event fires. 这意味着事件处理程序需要访问您创建的StreamWriter ,否则它需要打开输出文件本身,编写一个值,然后在每次事件触发时将其关闭。

Since you can't pass the StreamWriter to the event handler as an argument, the only way to give the event handler access to it is to make it a class-level variable, which you can't do from a static Main method. 由于您不能将StreamWriter作为参数传递给事件处理程序,因此赋予事件处理程序访问权限的唯一方法是使其成为类级别的变量,而静态Main方法无法做到这一点。 You'll probably have to create a class to hold both the FileSystemWatcher and the StreamWriter , and just instantiate that class from the Main method. 您可能必须创建一个类来同时容纳FileSystemWatcherStreamWriter ,然后只需从Main方法实例化该类。

But Wait, There's More! 但是,等等,还有更多!

What if you're in the process of writing to the StreamWriter, and another file gets created at that exact moment? 如果您正在写入StreamWriter的过程中,并且恰好在此刻创建了另一个文件,该怎么办? You can't have two threads writing to a single StreamWriter at the same time, or Bad Things are inevitable. 您不能有两个线程同时写入一个StreamWriter,否则不可避免的是坏事。 So you'll need to protect access to the StreamWriter using some sort of locking. 因此,您需要使用某种锁定保护对StreamWriter的访问。

You need to call 你需要打电话

fileWriter.Write(data);

Additionally, you should wrap it up like this: 此外,您应该像这样包装它:

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

This will write data to the filesystem and it should trigger your FileSystemWatcher object. 这会将数据写入文件系统,并且应该触发FileSystemWatcher对象。

edit -- inplace example 编辑-就地示例

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

I'd just use Log4Net and not worry about thread safety or any of the other gory details. 我只使用Log4Net ,而不用担心线程安全性或其他任何细节。

Put this in your AssemblyInfo.cs: 将其放在您的AssemblyInfo.cs中:

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

Every class that's going to log something needs a logger. 每个要记录内容的类都需要一个记录器。 Put this in each such class definition: 将其放在每个此类定义中:

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

The reason for the above is that it identifies each logger by its containing type. 上面的原因是,它通过其包含的类型来标识每个记录器。 Your log4net.config can filter/route/configure logging by logger, so by doing it this way, you get a great deal of control over the logging. 您的log4net.config可以通过logger过滤/路由/配置日志,因此通过这种方式,您可以对日志进行大量控制。 You can, say, dial up the logging verbosity on a particular class that appears to be misbehaving, whilst leaving the rest of the application only logging stuff at, say, the ERROR and FATAL levels. 您可以说,在看起来异常的特定类上增加日志记录的详细程度,而仅使应用程序的其余部分仅记录ERROR和FATAL级别的记录。

You can log a message via one of the ILog methods (just like Console.WriteLine() or string.Format() : 您可以通过ILog方法之一记录消息(就像Console.WriteLine()string.Format()

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

Set up your log4net.config file so it looks something like this: 设置您的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>

And you'll logging to the console and to a file. 然后,您将登录到控制台和文件。 Log4Net will take care of log file rollover and all the icky bits. Log4Net将负责日志文件翻转和所有有害位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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