2010-03-02 37 views

Trả lời

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

Cảm ơn! Btw, có chức năng thư viện nào không? –

+0

@David - Chắc chắn phải có. Tôi tin rằng các thư viện .NET đang dần chuyển sang các giao diện IEnumerable hơn. – ChaosPandion

+1

Tôi cần phải đọc một tập tin đã được mở bởi một quá trình khác vì vậy tôi sửa đổi như: 'sử dụng fs = new FileStream (filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); sử dụng sr = new StreamReader (fs) ' – User

71

Nếu bạn đang sử dụng .NET 4.0, bạn chỉ có thể sử dụng File.ReadLines.

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

val readLines : string -> seq<string> 
+0

Điều đó đòi hỏi phải giữ toàn bộ tập tin trong bộ nhớ cùng một lúc, hoặc nó có thể xử lý từng dòng? –

+12

"ReadLines và ReadAllLines phương pháp khác nhau như sau: Khi bạn sử dụng ReadLines, bạn có thể bắt đầu liệt kê bộ sưu tập của chuỗi trước khi toàn bộ bộ sưu tập được trả về, khi bạn sử dụng ReadAllLines, bạn phải chờ cho toàn bộ chuỗi chuỗi được trả về trước khi bạn có thể Vì vậy, khi bạn đang làm việc với các tệp rất lớn, ReadLines có thể hiệu quả hơn. " –

17

Để trả lời câu hỏi liệu có một chức năng thư viện để đóng gói mô hình này - không có một chức năng chính xác cho điều này, nhưng có một chức năng cho phép bạn tạo ra chuỗi từ một số trạng thái gọi là Seq.unfold . Bạn có thể sử dụng nó để triển khai chức năng ở trên như thế này:

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

Giá trị sr đại diện cho trình đọc luồng và được chuyển qua trạng thái. Miễn là nó cung cấp cho bạn các giá trị không null, bạn có thể trả lại Some chứa một phần tử để tạo và trạng thái (có thể thay đổi nếu bạn muốn). Khi nó đọc null, chúng tôi vứt bỏ nó và trả về None để kết thúc chuỗi. Đây không phải là một tương đương trực tiếp, bởi vì nó không xử lý đúng cách StreamReader khi một ngoại lệ được ném. Trong trường hợp này, tôi chắc chắn sẽ sử dụng biểu thức trình tự (có vẻ thanh lịch và dễ đọc hơn trong hầu hết các trường hợp), nhưng rất hữu ích khi biết rằng nó cũng có thể được viết bằng chức năng bậc cao hơn.

+0

về cách sử dụng này tôi nhận được ngoại lệ sau đây: {"Không thể đọc từ một TextReader đã đóng."} Tại dòng 'match sr.ReadLine() with'. bất kỳ giúp đỡ xin vui lòng là tại sao? – AruniRC

+0

@AruniRC Tôi nghĩ rằng giải pháp của @ChaosPandion là đẹp hơn nhiều so với một sử dụng 'unfold', vì vậy tôi sẽ đi với :-) –

+0

@AruniRC, Seq là lười biếng - bởi thời gian bạn đánh giá nó sau này trong mã , người đọc có thể đã bị đóng, do đó không thể đọc từ một TextReader đã đóng. Bạn sẽ phải buộc đánh giá trình tự ngay lập tức, ví dụ bằng cách chuyển đổi sang danh sách với 'Seq.toList' hoặc một số mẹo khác. –

3

On NET 2/3 bạn có thể làm:

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

và trên NET 4:

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

Cái đầu tiên trong số này không phải là lười ('ReadAllLines' háo hức đọc tất cả các dòng vào một mảng). –

8
let lines = File.ReadLines(path)     

    // To check 
    lines |> Seq.iter(fun x -> printfn "%s" x) 
Các vấn đề liên quan