RのSkyrim Mod開発日記

SkyrimのMod開発を中心に、備忘録などを載せていきます。

簡易ログビューワーの作成 - タイマー処理版

SkyrimPapyrusのログは常にファイル更新するわけではないので、タイマー処理でストリームに追記がある場合に、読み取る必要があることが分かりました。
またいくつかの問題もわかりましたので、次の編集を加えます。

  • TextBoxではなくRichTextBoxにする

ログファイルの改行コードはLFなので、そのままTextBoxに貼り付けると改行しませんので、RichTextBoxに変更します。

  • タイマーを追加する
  • タイマーイベントでは前回からファイルサイズ(length)が変更されているかで判断することにします

以下、変更後の全ソースコードです。

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;
        long pos;
        long len;
        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, richTextBox1);
            pos = fs.Position;
            len = fs.Length;

            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (fs.Length != len)
            {
                fs.Seek(pos, SeekOrigin.Begin);
                ReadFile(fs, richTextBox1);
                pos = fs.Position;
                len = fs.Length;
            }
        }

        static void ReadFile(FileStream fs, RichTextBox 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();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            fs.Close();
        }
    }
}

なお、テスト版として作っているものなので、作りはかなり適当です。
一応、ある程度見込みが出来たので、これからどのようなログビューワーとするかを考えていきたいと思います。