C#で簡易ログビューワーの作成 - とりあえずこれでいいんじゃない？

# はじめに
SkyrimのMod開発に手を染め、デバッグ時のログ確認をするのに、既存のツールが気に食わなかったので、自作することにしました。
本記事は、自作ログビューワーの内、試行錯誤した結果、ファイル操作はとりあえずこれくらいできていればいいや、というクラスを丸ごとさらしています。
今現在、一応それなりに動いているので、これでいいんじゃないかなと思っています。

<font color=red><b>なお、コメントはほとんど記入していません。もっと詳しく解説してという方がいらっしゃいましたら、コメントください。</b></font>

# ソースコード
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace WindowsFormsApplication1
{
    class LogReader
    {
        private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
        private FileStream fs;
        private long len;
        private Encoding encoding;

        public event EventHandler Renewted;
        public event ReadedEventHandler Readed;

        public LogReader()
        {
            timer.Tick += new System.EventHandler(timer_Tick);

            //TODO:その内プロパティ化
            encoding = System.Text.Encoding.GetEncoding(932);
        }
        ~LogReader()
        {
            if (fs != null)
            {
                fs.Close();
                fs.Dispose();
            }
            timer.Dispose();
        }

        public int Interval
        {
            get
            {
                return timer.Interval;
            }
            set
            {
                timer.Interval = value;
            }
        }

        public void ReadStart(string filePath, int interval = 100)
        {
            if (fs != null)
            {
                timer.Enabled = false;
                fs.Close();
                OnRenewted(new EventArgs());
            }

            //TODO: 必要そうならその内、開き方を指定できるようにする
            fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

            Interval = interval;
            timer.Enabled = true;
        }
        public void ReadStop()
        {
            timer.Enabled = false;
        }
        public void ReadRestart()
        {
            timer.Enabled = true;
        }

        protected virtual void OnRenewted(EventArgs e)
        {
            len = 0;

            if (Renewted != null)
                Renewted(this, e);
        }

        protected virtual void OnReaded(ReadedEventArgs e)
        {
            if (Readed != null)
                Readed(this, e);
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            long length = fs.Length;

            //ファイルサイズが小さくなったら、ログが変わったと判断する
            if (length < len)
                OnRenewted(new EventArgs());

            //長さが大きくなっていたら、ログが追記されたと判断する
            if (length > len)
            {
                //TODO: 最初に大容量のファイルを開かれた場合、問題になるかもしれないので、その内検証する
                byte[] bs = new byte[length - len];
                fs.Seek(len, SeekOrigin.Begin);
                if (0 < fs.Read(bs, 0, bs.Length))
                    OnReaded(new ReadedEventArgs(encoding.GetString(bs)));
                len = length;
            }
        }
    }

    public delegate void ReadedEventHandler(object sender, ReadedEventArgs e);

    public class ReadedEventArgs : EventArgs
    {
        public string Text { get; }
        public ReadedEventArgs(string text)
        {
            Text = text;
        }
    }
}
```
# 使用例
```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;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private LogReader log = new LogReader();

        public Form1()
        {
            InitializeComponent();
            log.Renewted += (x, y) =>
            {
                richTextBox1.Text = "";
            };
            log.Readed += (x, y) =>
            {
                richTextBox1.Text += y.Text;
            };
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            log.ReadStart(@"C:\Hoge.log");
        }
    }
}
```

# 関連記事
- [C#で簡易ログビューワーの作成 - ファイル監視で行う](http://qiita.com/rrryutaro/items/5555c24cc4045e7d7105)
- [C#でRichTextBoxに書式を損なわずにテキストの追記を行う（Rtfでの追記）](http://qiita.com/rrryutaro/items/8042705a1a5acff4c4c7)
- [C#のRichTextBoxで描画処理を追加する](http://qiita.com/rrryutaro/items/76f1a2be939cbd3aaa09)

以上