1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C# テキストファイルを最終行から行単位で読み出す

Last updated at Posted at 2023-02-14

下の関連記事を書いた後、最終行から先頭に向けて一行ずつ読み出す方が使い易いんじゃないかと思い作ってみました。

行区切りが空白文字でないと期待どおり動かないと思います。

  • 本記事のすべての情報は利用者の責任において使ってください。
  • 本記事の情報が正しいこと、誤っていること、実行効率を検証していません。
  • 動作することも、動作しないことも保証しません。

誤りや改善案はご指摘いただければ感謝します。が、修正できない場合があることをご了承ください。

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;
    }
}

関連記事

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?