0
 private string last = string.Empty;
 private void Watcher_Changes(object sender, FileSystemEventArgs e) {
   try {
     var info = new FileInfo(e.FullPath);
     var size = info.Length;

     string output = $ "[*] {e.ChangeType}: \"{e.FullPath}\": \"{size}\"";

     if (last.Equals(output))
       return;

     Println(output);
     last = output;
   } catch (Exception ex) {
     PrintErr(ex);
   }
 }

Now i'm just showing the file size either if changed or not. but i want that only if the file size has changed then show the size in the output string :

string output = $"[*] {e.ChangeType}: \"{e.FullPath}\": \"{size}\"";

What i'm trying to do is to use MD5 but not sure how to use it next. This is what i did so far.

I added a new method :

private byte[] CheckSize(string filename)
        {
            using (MD5 md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(filename))
                {
                    return md5.ComputeHash(stream);
                }
            }
        }

Then in the changes event :

byte[] checkedsize = CheckSize(e.FullPath);

but not sure what to do with the byte array next ?

private void Watcher_Changes(object sender, FileSystemEventArgs e)
        {
            try
            {
                var info = new FileInfo(e.FullPath);
                var size = info.Length;

                byte[] checkedsize = CheckSize(e.FullPath);

                string output = $"[*] {e.ChangeType}: \"{e.FullPath}\": \"{size}\"";

                if (last.Equals(output))
                    return;

                Println(output);
                last = output;
            }
            catch (Exception ex)
            {
                PrintErr(ex);
            }
        }
Daniel Lip
  • 3,867
  • 7
  • 58
  • 120
  • 4
    Use a `Dictionary` to remember the filepath -> filesize last time, then update it this time ready for next time – Caius Jard May 08 '22 at 14:19
  • 1
    You can use also a hash (https://stackoverflow.com/a/10520086/18452174) instead of check only the size. The size maybe the same after edit a file and you don't detect the change. – Victor May 08 '22 at 14:39
  • @Victor i edited my question with what i tried using the MD5. I created a new method that return byte array of a file but not sure what to do with the byte array next in the changes event. – Daniel Lip May 08 '22 at 17:27
  • @CaiusJard i first tried victor solution because i'm not sure how to do it with a dictionary. can you give me some code of how it should be with dictionary please ? – Daniel Lip May 08 '22 at 17:28
  • Victor's solution uses a dictionary, and is very similar to something I wrote years ago. What doesn't your code do that you wish it did? – Caius Jard May 08 '22 at 19:31
  • @CaiusJard I have two projects. the first using wpf and filesystemwatcher to monitor files changes. the second project is winforms and is just for help testing the wpf project. the winforms project create some images with random sizes each image in a random size and after 5 second the images files get deleting and then after another 5 seconds the images file creating again and so on nonstop create/delete. – Daniel Lip May 08 '22 at 20:08
  • @CaiusJard The wpf project monitor the images and the problem i think it's a problem when the images file creating the wpf project monitor it as change but also as create. and i want it to be account only as created and not changed. when it's deleting the files and create them again it's monitoring them as created but also changed because i think it's taking a bit time to create image files some of them a bit bigger in size so this small of time to create it is like changed. – Daniel Lip May 08 '22 at 20:09
  • @CaiusJard for exmaple image file created. first the file size is 0bytes then 24bytes then 600bytes then 1kb in the end 25kb all this count as changed but since the file was not exist before it also counted as created. and i think in this case it should be count only as created. or i'm wrong with this logic ? in my logic changed meaning size changed after the file finished created and not while creating it. and i'm not sure how to make the separate between the created and changed. – Daniel Lip May 08 '22 at 20:12
  • @CaiusJard i can add both small projects to my onedrive. they are very small projects. – Daniel Lip May 08 '22 at 20:13
  • 1
    Sure, link us to the source code – Caius Jard May 08 '22 at 20:16
  • @CaiusJard The folder name is My Projects. two rar files each for each project. https://1drv.ms/u/s!AmVw2eqP6FhB2DN3vDMbqXfEk46F?e=7ORW7q – Daniel Lip May 08 '22 at 21:12
  • What is your intent with the MD5? Rereading a file and computing a new MD5 every time it changes will be quite intense – Caius Jard May 09 '22 at 05:13
  • @CaiusJard no really intent with the MD5. I was mistaken. I want to solve the problem that when creating a file like image or any file and if he is a bit bigger in size the filesystemwatcher think the file has changed instead only created as first time. maybe show the file as changed is also option because the file creating from 0 to some size but i want also to have the option that a new created file will be displayed only as created and not also as changed. this is my problem. – Daniel Lip May 09 '22 at 06:43
  • 1
    I've run your apps for 5 minutes and haven't once observed a case where a file was Created and the event was reported as Changed, but for any given file you'll see a Created followed by a Changed so if you only heed the latter event you'll detect it as changed ... https://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice has some relevant tips – Caius Jard May 09 '22 at 10:49

1 Answers1

1

With a Dictionary you can save info based in some key. You can match pairs, like "FileFullPath" and "Some class with information about that you need". For example:

public class FileChangeInfo
{
    public byte[] Hash { get; set; }
    public DateTime Date { get; set; }

    public bool IsModified(FileChangeInfo fileChangeInfo)
    {
        var cmp = this.Date.CompareTo(fileChangeInfo.Date);
        if (cmp != 0)
        {
            return true;
        }

        cmp = this.Hash.Length.CompareTo(fileChangeInfo.Hash.Length);
        if (cmp != 0)
        {
            return true;
        }

        return !this.Hash.SequenceEqual(fileChangeInfo.Hash);
    }
}

Define your dictionary:

private readonly Dictionary<string, FileChangeInfo> _changeInfoByPath =
    new Dictionary<string, FileChangeInfo>(StringComparer.OrdinalIgnoreCase);

And use in your method:

var newFileChangeInfo = new FileChangeInfo
{
    Hash = CheckSize(e.FullPath),
    Date = DateTime.UtcNow
};

if (this._changeInfoByPath.TryGetValue(e.FullPath, out FileChangeInfo info))
{
    // Compare current info stored previously
    if (info.IsModified(newFileChangeInfo))
    {
        // File has changes. Do whatever you want...

        // and update the current file info for future changes
        this._changeInfoByPath[e.FullPath] = newFileChangeInfo;
    }
}
else
{
    // First time: add to dictionary for future comparisons
    this._changeInfoByPath.Add(e.FullPath, newFileChangeInfo);
}
Victor
  • 2,313
  • 2
  • 5
  • 13