下の関連記事を書いた後、最終行から先頭に向けて一行ずつ読み出す方が使い易いんじゃないかと思い作ってみました。
行区切りが空白文字でないと期待どおり動かないと思います。
- 本記事のすべての情報は利用者の責任において使ってください。
- 本記事の情報が正しいこと、誤っていること、実行効率を検証していません。
- 動作することも、動作しないことも保証しません。
誤りや改善案はご指摘いただければ感謝します。が、修正できない場合があることをご了承ください。
Program.cs
static void Main(string[] _)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
using FileStream stream = new(
@"C:\temp\新規 テキスト ドキュメント.txt",
FileMode.Open,
FileAccess.Read
);
var enc = Encoding.GetEncoding("shift_jis");
foreach (var r in FileStreamExtension.Tail(stream, enc))
{
Console.WriteLine(r);
}
}
FileStreamExtension
public static class FileStreamExtension
{
public static IEnumerable<string> Tail(
this FileStream stream,
Encoding encoding,
string delimiter = "\r\n"
)
{
if (string.IsNullOrEmpty(delimiter)) throw new ArgumentException($"empty delimiter");
if (stream.Length <= 0) yield break;
Stack<byte> stack = new();
stream.Position = stream.Length - 1;
while (stream.Position >= 1)
{
int buffer = stream.ReadByte();
stack.Push((byte)buffer);
if (buffer == delimiter[0])
{
// 読みだした文字が指定されたデリミタの先頭文字と同じ場合は検査する
var s = encoding.GetString(stack.ToArray());
if (s.IndexOf(delimiter, 0) == 0)
{
ForwardPosition();
stack.Clear();
yield return s == delimiter ? "" : s.TrimStart();
}
}
else
{
ForwardPosition();
}
}
if (stream.Position == 0)
{
stack.Push((byte)stream.ReadByte());
var s = encoding.GetString(stack.ToArray());
yield return s == delimiter ? "" : s.TrimStart();
}
void ForwardPosition() => stream.Position -= 2;
}
}
関連記事