簡易Tailコマンド

リングバッファーを使った Tailコマンドです。

コマンドの書式は、

というとても単純なものです。たとえば、sample.txtの最後の30行を表示したい場合は、

のように入力します。 行数を省略した場合は、最後の10行が表示されます。

また、ファイル名を省略した場合は、 標準入力からの入力となります。

自作のRingBufferクラスを利用し、Tailコマンドを実装しています。
RingBufferは、リング状に配置されたバッファーで、一定の量だけを保存するために 利用するデータ構造です。

Wikipediaに説明がありますので、リングバッファとは何かという説明は割愛します。

wikipwdia:リングバッファ
http://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B0%E3%83%90%E3%83%83%E3%83%95%E3%82%A1

ここで作成した RingBufferクラスは、

とジェネリッククラスにしているので、用途にあった型のデータを入れることができます。

また、IEnumerable<T> を実装していますので、foreachで簡単に要素を取り出す ことができます。
なお、この実装では、取り出した要素は、バッファから削除していますので、 同じ要素を複数回バッファーの中から取り出すことはできません。

RingBuffer の簡単な使い方を示します。

このコードを実行すると、以下のように最後に追加した4つの文字列が表示されます。

 

このプログラムの実質的なメイン部分は、DoTailメソッドです。(コードは最後に載せています)
見ていただければわかると思いますが、
 「ファイルを1行ずつ読み込み、RingBufferに追加していき、
    最後まで読み終わったら、RingBufferの中身をforeachで書き出す」
という、とてもシンプルなコードになっています。

シンプルなコードとなったのは、RingBufferクラスの存在が大きいですね。
こういったクラスがなかったら、 かなり複雑なコードを書かないといけなくなってしまいますし、デバッグも大変です。

RingBufferクラスは、ある程度汎用性を持たせましたが、 一般的なRingBufferのインターフェースが良くわからないので、私なりのインターフェースとしました。
他の用途で利用するには、機能不足のところもあるかもしれません。
特に、Get や foreachでデータを取り出した時に、バッファからデータを除去する仕様としましたが、 除去したくない場合もあると思います。そのような場合は、新たなメソッドを追加する必要があります。

一方、Tailコマンドでの利用だけを考えた場合は、オーバースペックの部分があります。
こういった汎用クラスは、設計がなかなか難しいものです。

以下、C#のコードです。

■RingBuffer.cs  


■Program.cs