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.
let readLines (filePath:string) = seq {
use sr = new StreamReader (filePath)
while not sr.EndOfStream do
yield sr.ReadLine ()
}
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>
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.
let lines = File.ReadLines(path)
// To check
lines |> Seq.iter(fun x -> printfn "%s" x)
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);;
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" }