web-dev-qa-db-fra.com

Comment lire un fichier dans une séquence de lignes en F #

Il s'agit de la version 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();
    }
  }
}

Mais la traduction directe nécessite une variable mutable.

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

Si vous utilisez .NET 4.0, vous pouvez simplement utiliser File.ReadLines .

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

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

Pour répondre à la question de savoir s'il existe une fonction de bibliothèque pour encapsuler ce modèle - il n'y a pas de fonction exactement pour cela, mais il existe une fonction qui vous permet de générer une séquence à partir d'un état appelé Seq.unfold. Vous pouvez l'utiliser pour implémenter les fonctionnalités ci-dessus comme ceci:

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

La valeur sr représente le lecteur de flux et est transmise comme état. Tant qu'il vous donne des valeurs non nulles, vous pouvez retourner Some contenant un élément à générer et l'état (qui peut changer si vous le souhaitez). Lorsqu'il lit null, nous le supprimons et renvoyons None pour terminer la séquence. Ce n'est pas un équivalent direct, car il ne dispose pas correctement de StreamReader lorsqu'une exception est levée.

Dans ce cas, j'utiliserais certainement l'expression de séquence (qui est plus élégante et plus lisible dans la plupart des cas), mais il est utile de savoir qu'elle pourrait également être écrite à l'aide d'une fonction d'ordre supérieur.

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

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

Sur .NET 2/3, vous pouvez faire:

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

et sur .NET 4:

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

Afin d'éviter la "System.ObjectDisposedException: Impossible de lire à partir d'un TextReader fermé." exception, utilisez:

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