web-dev-qa-db-ja.com

F#でファイルを連続した行に読み込む方法

これはC#バージョンです。

public static IEnumerable<string> ReadLinesEnumerable(string path) {
  using ( var reader = new StreamReader(path) ) {
    var line = reader.ReadLine();
    while ( line != null ) {
      yield return line;
      line = reader.ReadLine();
    }
  }
}

ただし、直接翻訳するには可変変数が必要です。

51
Yin Zhu
let readLines (filePath:string) = seq {
    use sr = new StreamReader (filePath)
    while not sr.EndOfStream do
        yield sr.ReadLine ()
}
64
ChaosPandion

.NET 4.0を使用している場合は、 File.ReadLines を使用できます。

> let readLines filePath = System.IO.File.ReadLines(filePath);;

val readLines : string -> seq<string>
85
Joel Mueller

このパターンをカプセル化するライブラリ関数があるかどうかの質問に答えるために、関数exactlyはありませんが、Seq.unfoldと呼ばれる状態からシーケンスを生成できる関数があります。これを使用して、上記の機能を次のように実装できます。

new StreamReader(filePath) |> Seq.unfold (fun sr -> 
  match sr.ReadLine() with
  | null -> sr.Dispose(); None 
  | str -> Some(str, sr))

sr値はストリームリーダーを表し、状態として渡されます。 null以外の値を提供する限り、生成する要素と状態(必要に応じて変更可能)を含むSomeを返すことができます。 nullを読み取ると、それを破棄し、Noneを返してシーケンスを終了します。例外がスローされたときにStreamReaderを適切に破棄しないため、これは直接の同等物ではありません。

この場合、私は間違いなくシーケンス式(ほとんどの場合によりエレガントで読みやすい)を使用しますが、高次関数を使用して記述できることを知っておくと便利です。

18
Tomas Petricek
    let lines = File.ReadLines(path)                

    // To check
    lines |> Seq.iter(fun x -> printfn  "%s" x) 
11
maria

.NET 2/3では次のことができます。

let readLines filePath = File.ReadAllLines(filePath) |> Seq.cast<string>

および.NET 4の場合:

let readLines filePath = File.ReadLines(filePath);;
5
Lars Tackmann

「System.ObjectDisposedException:閉じたTextReaderから読み取れません。」を回避するため例外、使用:

let lines = seq { yield! System.IO.File.ReadLines "/path/to/file.txt" }
0
Ilya Kharlamov