[英]How read a file into a seq of lines in F#
This is C# 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();
}
}
}
But directly translating needs a mutable variable.但是直接翻译需要一个可变变量。
If you're using .NET 4.0, you can just use File.ReadLines .如果您使用的是 .NET 4.0,则可以只使用File.ReadLines 。
> let readLines filePath = System.IO.File.ReadLines(filePath);;
val readLines : string -> seq<string>
open System.IO
let readLines (filePath:string) = seq {
use sr = new StreamReader (filePath)
while not sr.EndOfStream do
yield sr.ReadLine ()
}
To answer the question whether there is a library function for encapsulating this pattern - there isn't a function exactly for this, but there is a function that allows you to generate sequence from some state called Seq.unfold
.要回答是否有用于封装此模式的库函数的问题 - 没有完全用于此的函数,但有一个函数允许您从称为
Seq.unfold
某个状态生成序列。 You can use it to implement the functionality above like this:您可以使用它来实现上述功能,如下所示:
new StreamReader(filePath) |> Seq.unfold (fun sr ->
match sr.ReadLine() with
| null -> sr.Dispose(); None
| str -> Some(str, sr))
The sr
value represents the stream reader and is passed as the state. sr
值表示流读取器并作为状态传递。 As long as it gives you non-null values, you can return Some
containing an element to generate and the state (which could change if you wanted).只要它为您提供非空值,您就可以返回
Some
包含要生成的元素和状态(如果您愿意,可以更改)。 When it reads null
, we dispose it and return None
to end the sequence.当它读取
null
,我们处理它并返回None
以结束序列。 This isn't a direct equivalent, because it doesn't properly dispose StreamReader
when an exception is thrown.这不是直接的等价物,因为它在抛出异常时没有正确处理
StreamReader
。
In this case, I would definitely use sequence expression (which is more elegant and more readable in most of the cases), but it's useful to know that it could be also written using a higher-order function.在这种情况下,我肯定会使用序列表达式(在大多数情况下它更优雅且更具可读性),但知道它也可以使用高阶函数编写是很有用的。
let lines = File.ReadLines(path)
// To check
lines |> Seq.iter(fun x -> printfn "%s" x)
On .NET 2/3 you can do:在 .NET 2/3 上,您可以执行以下操作:
let readLines filePath = File.ReadAllLines(filePath) |> Seq.cast<string>
and on .NET 4:在 .NET 4 上:
let readLines filePath = File.ReadLines(filePath);;
In order to avoid the "System.ObjectDisposedException: Cannot read from a closed TextReader."为了避免“System.ObjectDisposedException:无法从关闭的 TextReader 读取”。 exception, use:
例外,使用:
let lines = seq { yield! System.IO.File.ReadLines "/path/to/file.txt" }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.