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$
1
  • $\begingroup$ Further update $\endgroup$
    – William
    Oct 5, 2014 at 23:10

1 Answer 1

4
$\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 and acknowledge you have read our privacy policy.

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