1

My goal is to read the last inserted lines from a txt file and show only newly inserted lines in the console. Here is my code-

class Program
    {
        static void Main(string[] args)
        {
            string path = @"D:\tmp";

            MonitorFile(path);

            Console.ReadKey();
        }

        private static void MonitorFile(string path)

        { 

            FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();

            fileSystemWatcher.Path = path;

            fileSystemWatcher.Filter = "file.txt";

            fileSystemWatcher.Changed += FileSystemWatcher_Changed;

            fileSystemWatcher.EnableRaisingEvents = true;

        }

        private static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)

        {
            Console.WriteLine("");    //From here new inserted lines should be showed on the console.
        }
    }

My target is that each time new lines will be added at the last of the text file and only inserted new lines will come one after another in console. Here I used FileSystemWatcher for identify the change in the txt file but it seems like inserted data can't be read from FileSystemWatcher. Any help will be really appreciable.

  • Maybe: when the event is fired, store the size of the file in bytes. Next time it is fired, the new size of the file minus the old size is the number of bytes added/removed. – 001 Nov 22 '21 at 14:44
  • Thank you for your reply. But I need to read the text which was last added in the text file. – Aloukik Roy Nov 22 '21 at 14:48

3 Answers3

1

FileSystemWatcher used to watch filesystem changes not file content changes. The Changed event will be fired if the watched entry changes which will happen if the file size grows. So there is a connection between file content change and the event. But you must understand it is not because the file changes but because the filesystem entry describing some of your file's metadata changes.

If you need the added lines from the changed file then open the file via FileStream and read it in the Changed event handler. I would open the file in read-only mode without locks so the other process which writes to it wont get blocked because of this. If you need only the appended lines then use technique others suggested: save the last file Position you saw and next time after opening file just seek to that position, read till end the news then save the current position again.

cly
  • 661
  • 3
  • 13
0

I think now it'll work:

class Program
{
    public static string lastValue = string.Empty;
    public static string folderPath = AppDomain.CurrentDomain.BaseDirectory;
    public static string fileName = "file.txt";

    static void Main(string[] args)
    {
        MonitorFile(folderPath);
        Console.ReadKey();
    }

    private static void MonitorFile(string path)
    {
        lastValue = File.ReadAllLines(folderPath + fileName).Last();
        FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
        fileSystemWatcher.Path = path;
        fileSystemWatcher.Filter = fileName;
        fileSystemWatcher.Changed += FileSystemWatcher_Changed;
        fileSystemWatcher.EnableRaisingEvents = true;
    }

    private static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.ChangeType != WatcherChangeTypes.Changed)
        {
            return;
        }

        var numberOfRetries = 3;
        var delayOnRetry = 500;

        for (int i = 1; i <= numberOfRetries; ++i)
        {
            try
            {
                var lines =  File.ReadAllLines(folderPath + fileName).ToList();
                var lastLine = lines.Last();

                if (lastLine != lastValue)
                {
                    var index = lines.LastIndexOf(lastValue) + 1;
                    var newLines = lines.GetRange(index, lines.Count - index);
                    lastValue = newLines.Last();
                    newLines.ForEach(Console.WriteLine);
                }
                break; 
            }
            catch (IOException) when (i <= numberOfRetries)
            {
                Thread.Sleep(delayOnRetry);
            }
        }
    }
}

But there may be a problem with permissions here. If you change folderPath to this:

public static string folderPath = AppDomain.CurrentDomain.BaseDirectory;

And put your file near the DLL file (bin\Debug folder), it'll work for sure.

Dori
  • 31
  • 4
-2

If your file is not so big:

File.ReadLines(@"c:\file.txt").Last();
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Giorgio
  • 1
  • 1