5
$\begingroup$

How might I watch for a specific file to change in a directory using Mathematica/.NET code?

The following works in .NET but fires twice when you change the file.

using System;

public class Watcher
{
    public static int exit=1;
    static DateTime lastRead = DateTime.MinValue;
    public static void Main()
    {
        System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher();
        watcher.Path = "C:\\Users\\a\\Desktop";
        watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite;
        watcher.Filter = "test.txt";
        watcher.Changed += new System.IO.FileSystemEventHandler(OnChanged);
        watcher.EnableRaisingEvents = true;
        while (exit != 0) ;
    }
    private static void OnChanged(object source, System.IO.FileSystemEventArgs e)
    {
        DateTime lastWriteTime = System.IO.File.GetLastWriteTime(e.FullPath);
        if (lastWriteTime != lastRead)
        {
            Console.Write(
              System.IO.File.ReadAllText(e.FullPath)
            );
            exit = 0;
            lastRead = lastWriteTime;
        }
    }
}

to compile

C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe test.cs

Here is the starting code for Mathematica.

Needs["NETLink`"];
InstallNET[];
myHandler[source_, e_] := Print["File editted"];
w = NETNew["System.IO.FileSystemWatcher"];
LoadNETType["System.IO.NotifyFilters"];
w@Path = "C:\\Users\\a\\Desktop";
w@NotifyFilter = NotifyFilters`LastWrite;
w@Filter = "*.txt";
e = AddEventHandler[w@Changed, myHandler];
w@EnableRaisingEvents = True;
$\endgroup$
  • $\begingroup$ Further update $\endgroup$ – William Oct 5 '14 at 23:10
3
$\begingroup$

There are 2 techniques. Because of the following bug here(or feature).

Needs["NETLink`"];
InstallNET[];

ShowNETConsole["stdout"];
LoadNETType["System.Console"];
Console`Out@WriteLine["Hello from .NET"];

WatchFile[file_String, fun_] := 
  Module[{time, time2, w, e},
   w = NETNew["System.IO.FileSystemWatcher"];
   LoadNETType["System.IO.NotifyFilters"];
   LoadNETType["System.IO.File"];
   w@Path = FileNameJoin@Drop[FileNameSplit[file], -1];
   w@NotifyFilter = NotifyFilters`LastWrite;
   w@Filter = Last@FileNameSplit[file];
   e = AddEventHandler[w@Changed, myHandler];
   time = 0;
   myHandler[source_, e_] := (
     time2 = File`GetLastWriteTime[file]@ToBinary[];
     If[time == time2,
      Null;,
      fun[source,e];];
     time = time2;
     );
   w@EnableRaisingEvents = True;
   Return[{w, e}];];
WatchFile["C:\\cygwin64\\home\\a\\test.txt", 
 Function[{w, e}, Console`Out@WriteLine[e@FullPath]]]

Along with the following technique with watching for content to change in the myHandler.

content = Import[file, "Plaintext"];
myHandler[source_, e_] := (
   content2 = Import[file, "Plaintext"];
   If[content != content2,
    fun[source,e];
    ];
   content = content2;
   );
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.