Как прочитать файл в последовательность строк в F # - PullRequest
51 голосов
/ 02 марта 2010

Это версия 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 ]

85 голосов
/ 02 марта 2010

Если вы используете .NET 4.0, вы можете просто использовать File.ReadLines .

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

val readLines : string -> seq<string>
64 голосов
/ 02 марта 2010
let readLines (filePath:string) = seq {
    use sr = new StreamReader (filePath)
    while not sr.EndOfStream do
        yield sr.ReadLine ()
}
18 голосов
/ 03 марта 2010

Чтобы ответить на вопрос, существует ли библиотечная функция для инкапсуляции этого шаблона - для этого нет функции точно , но есть функция, которая позволяет генерировать последовательность из некоторого состояния, называемого 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 при возникновении исключения.

В этом случае я бы определенно использовал выражение последовательности (которое в большинстве случаев более изящно и более читабельно), но полезно знать, что оно также может быть записано с использованием функции более высокого порядка.

11 голосов
/ 02 августа 2013
    let lines = File.ReadLines(path)                

    // To check
    lines |> Seq.iter(fun x -> printfn  "%s" x) 
5 голосов
/ 01 августа 2011

В .NET 2/3 вы можете сделать:

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

и в .NET 4:

let readLines filePath = File.ReadLines(filePath);;
0 голосов
/ 03 апреля 2019

Во избежание «System.ObjectDisposedException: невозможно прочитать из закрытого TextReader». исключение, используйте:

let lines = seq { yield! System.IO.File.ReadLines "/path/to/file.txt" }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...