C#で簡易ログビューワーの作成 - ファイル監視で行う

#はじめに
作りは適当なので、参考程度にしてください。例外処理など一切対処していません。

#やりたいこと
- TextBoxにて指定のテキストファイルを読み込み、その後ファイルの変更があったら続きをTextBoxに追記する
- ファイルシステムウォッチャー(FileSystemWatcher)を利用する
- ファイル読込はByte形式で、指定バイト数を繰り返して読むことにする

#ポイント
##ファイルシステムウォッチャーでファイル監視する

```csharp
String fileName = ""; //任意のファイルパス

//ファイルを読込専用、他プロセスからの読書き可能として開き、読込んで読込み位置を取得する
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

//指定のファイルのみ更新された際に、非同期にイベントを呼出す
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = System.IO.Path.GetDirectoryName(fileName);
fsw.Filter = System.IO.Path.GetFileName(fileName);
fsw.NotifyFilter = NotifyFilters.LastWrite;
fsw.Changed += new FileSystemEventHandler(fsw_Changed);	
fsw.SynchronizingObject = this;
fsw.EnableRaisingEvents = true;
```

#ソースコード全体

```csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace SimpleLogViewer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        FileStream fs;
        FileSystemWatcher fsw;
        long pos;
        private void Form1_Load(object sender, EventArgs e)
        {
            //オープンファイルダイアログを表示
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.ShowDialog();

            //TODO:ファイルが選ばれなかった場合などの処理が必要

            //ファイルを読込専用、他プロセスからの読書き可能として開き、読込んで読込み位置を取得する
            fs = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            ReadFile(fs, textBox1);
            pos = fs.Position;

            //指定のファイルのみ、更新された際に非同期にイベントを呼出す
            fsw = new FileSystemWatcher();
            fsw.Path = Path.GetDirectoryName(dlg.FileName);
            fsw.Filter = Path.GetFileName(dlg.FileName);
            fsw.NotifyFilter = NotifyFilters.LastWrite;
            fsw.Changed += new FileSystemEventHandler(fsw_Changed);
            fsw.SynchronizingObject = this;
            fsw.EnableRaisingEvents = true;
        }

        static void ReadFile(FileStream fs, TextBox tb)
        {
            //ファイルを一時的に読み込むバイト型配列を作成する
            byte[] bs = new byte[0x1000];
            //ファイルをすべて読み込む
            for (;;)
            {
                //ファイルの一部を読み込む
                int readSize = fs.Read(bs, 0, bs.Length);
                //ファイルをすべて読み込んだときは終了する
                if (readSize == 0)
                    break;
                //部分的に読み込んだデータを使用したコードをここに記述する
                tb.Text += System.Text.Encoding.GetEncoding(932).GetString(bs);
            }
            //カーソルを行末に移動して、スクロールさせる
            tb.SelectionStart = tb.Text.Length;
            tb.ScrollToCaret();
        }

        void fsw_Changed(object sender, FileSystemEventArgs e)
        {
            //ファイルの先頭から指定した位置までストリーム内の読込み位置を変更し、追加分のデータを読込んで、読込み位置を最後の位置にする
            fs.Seek(pos, SeekOrigin.Begin);
            ReadFile(fs, textBox1);
            pos = fs.Position;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            fs.Close();
            fsw.EnableRaisingEvents = false;
            fsw.Dispose();
        }
    }
}
```
#関連記事
- （はてなブログ）[簡易ログビューワーの作成](http://rrryutaro.hatenablog.com/entry/2016/12/19/201301)
- （Qiita）[C#で簡易ログビューワーの作成 - とりあえずこれでいいんじゃない？](http://qiita.com/rrryutaro/items/3a6b01f379aa5b3c696c)

以上