三浦ノート

自分の経験したことを検索可能にしていくブログ.誰かの役に立ってくれれば嬉しいです.

C#でStreamReaderでテキストファイルの行ごとのリストを生成する拡張メソッド(非同期版も)

C#(.net6.0)でStreamReaderで読み込んだテキストファイルの行ごとのEnumerableリストを生成する拡張メソッドStreamReader.ReadAllLinesを定義します。

public static IEnumerable<string> ReadAllLines(this StreamReader it)
{
    string? line;
    while ((line = it.ReadLine()) != null) yield return line;
}

一行が長い可能性があったりして、メインスレッドを長時間止めたくないような場合は非同期に読み込みたいです。

そのための非同期版の拡張メソッドStreamReader.ReadAllLinesAsyncを定義します。

public static async IAsyncEnumerable<string> ReadAllLinesAsync(this StreamReader it)
{
    string? line;
    while ((line = await it.ReadLineAsync()) != null) yield return line;
}

使用例

public static class Program
{
    public static IEnumerable<string> ReadAllLines(this StreamReader it)
    {
        string? line;
        while ((line = it.ReadLine()) != null) yield return line;
    }

    public static async IAsyncEnumerable<string> ReadAllLinesAsync(this StreamReader it)
    {
        string? line;
        while ((line = await it.ReadLineAsync()) != null) yield return line;
    }

    public static void ForEach<T>(this IEnumerable<T> it, Action<T> consumer)
    {
        foreach (var item in it) consumer(item);
    }

    static async Task Main(string[] args)
    {
        // 同期版
        using var file1 = new StreamReader("test.txt");
        file1.ReadAllLines().ForEach(Console.WriteLine);

        Console.WriteLine();

        // 非同期版
        using var file2 = new StreamReader("test.txt");
        await file2.ReadAllLinesAsync().ForEachAsync(line => Console.WriteLine(line));
    }
}

ForEachAsyncは System.Linq.Async -version 6.0.1に入っているものです。