如何将文件读入F#中的seq行

时间:2010-03-02 18:07:26

标签: 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();
    }
  }
}

但直接翻译需要一个可变的变量。

6 个答案:

答案 0 :(得分:85)

如果您使用的是.NET 4.0,则可以使用File.ReadLines

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

val readLines : string -> seq<string>

答案 1 :(得分:64)

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

答案 2 :(得分:18)

回答是否存在用于封装此模式的库函数的问题 - 对此没有函数完全,但是有一个函数允许您从某个状态生成序列Seq.unfold。您可以使用它来实现上述功能:

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

sr值表示流阅读器,并作为状态传递。只要它为您提供非空值,您就可以返回包含要生成的元素的Some和状态(如果需要,可以更改)。当它读取null时,我们将其处理并返回None以结束序列。这不是直接的等价物,因为它在抛出异常时没有正确处理StreamReader

在这种情况下,我肯定会使用序列表达式(在大多数情况下它更优雅,更易读),但知道它也可以使用更高阶函数编写是有用的。

答案 3 :(得分:11)

    let lines = File.ReadLines(path)                

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

答案 4 :(得分:5)

在.NET 2/3上,你可以这样做:

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

和.NET 4:

let readLines filePath = File.ReadLines(filePath);;

答案 5 :(得分:0)

为了避免出现“ System.ObjectDisposedException:无法从关闭的TextReader中读取”。例外,请使用:

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